tsconfig.json中文手册(2023.10.25更新)

tsconfig.js配置项中文解析(2023.10.25更新)

Root 输入相关选项

files、include 与 exclude

指定哪些文件需要被 ts 处理, 当这些需要被 ts 处理的文件较少时, 可以考虑使用files字段, 如果需要被处理的文件比较多, 可以考虑使用includeexclude

json 复制代码
{
  "compilerOptions": {},
  "files": [
    "core.ts",
    "sys.ts",
    "types.ts",
    "scanner.ts",
    "parser.ts",
    "utilities.ts",
    "binder.ts",
    "checker.ts",
    "tsc.ts"
  ]
}

includeglob(不懂的可以百度) 的方式指定哪些文件需要被 ts 处理

json 复制代码
{
  "include": ["src/**/*", "tests/**/*"]
}

excludeglob的方式, 从include指定的文件中排除一些文件, 这些被排除的文件不会被 ts 处理

json 复制代码
{
  "exclude": ["src/**/*", "tests/**/*"]
}

需要注意的是: exclude 只会排除include范围中指定的文件, 如果某个文件在exclude的范围内, 但是该文件被include范围内的某个文件引用, 或者这个文件被声明在files中, 该文件依然会被 ts 处理

extends

extends 属性是 TypeScript 配置文件 tsconfig.json 中的一个配置项,用于指定一个基础配置文件,以继承其配置选项。这个基础配置文件可以是另一个 tsconfig.json 文件,允许在多个 TypeScript 项目中共享通用的配置,从而避免重复配置。

继承的配置文件:extends 属性的值应该是一个包含所需配置选项的有效 tsconfig.json 文件的相对或绝对路径。这个文件可以是项目内的另一个配置文件,也可以是外部的共享配置文件。

合并配置:当使用 extends 属性时,TypeScript 将合并基础配置文件和当前配置文件中的选项。如果存在冲突,当前配置文件中的选项将覆盖基础配置文件中的选项。这使得可以在基础配置的基础上进行自定义。

多级继承:可以创建多级继承结构,其中一个配置文件可以继承另一个配置文件,然后另一个配置文件可以再继承前一个文件,以便构建复杂的配置继承链。

相对路径和绝对路径:extends 属性可以使用相对路径或绝对路径来引用基础配置文件。相对路径是相对于当前配置文件的位置计算的。

错误处理:如果 TypeScript 在加载继承的配置文件时遇到错误,它将抛出一个错误并指出问题所在。这可以帮助快速发现配置问题。

配置继承的建议:使用 extends 属性可以提高配置文件的可维护性,但需要小心管理继承关系。确保基础配置文件的更改不会意外影响到依赖它的项目。同时,确保在每个项目中都有足够的文档来描述配置继承关系和特定配置项的含义。

比如下面的三个有继承关系的配置文件:

json 复制代码
// tsconfig.a.json
{
  "compilerOptions": {},
  "files": [
    "a.ts"
  ],
  "include": [
    "src/*"
  ]
}

// tsconfig.b.json
{
  "extends": "./tsconfig.a.json",
  "files": [
    "b.ts"
  ],
  "exclude": [
    "src/view/*"
  ]
}
// tsconfig.json
{
  "extends":"tsconfig.b.json",
  "files":["c.ts"]
}

当使用 ts 编译的时候, 这三个配置文件的合并结果是:

bash 复制代码
$ npx tsc --showConfig
{
    "compilerOptions": {},
    "files": [
        "./a.ts"
    ],
    "include": [
        "src/*"
    ],
    "exclude": [
        "src/view/*"
    ]
}

ts 官方提供了一些常用的配置文件,安装和使用方法可以点击这里

Emit 输出相关选项

outDir

如果设置了这个选项, ts 编译后生成的.js,.d.ts,.js.map文件都会保存在这个目录内

如果没有设置, 生成的文件会保存在源.ts文件的同级目录

outFile

如果设置了这个选项, ts 生成的所有文件都会保存在单个输出文件中

只有module选项的值为None,System,AMD时, 这个选项才有效

sourceMap

如果设置为true, ts 在编译后会生成映射文件.js.map, 并在.js文件结尾插入 sourceMappingURL, 像这样:

javascript 复制代码
import { init } from "foo";
console.log(init);
export var add = function () {};
//# sourceMappingURL=main.js.map

mapRoot

指定sourceMappingURL的前缀

假设有源文件:

typescript 复制代码
export const foo = "foo";

没有指定mapRoot时的输出内容:

javascript 复制代码
export var foo = "foo";
//# sourceMappingURL=main.js.map

指定了"mapRoot": "http://codquan2.com"时的输出内容:

javascript 复制代码
export var foo = "foo";
//# sourceMappingURL=http://codquan2.com/main.js.map

sourceRoot

指定.js.map文件中的sourceRoot字段(用于指定源代码文件的根目录,通常用于调试和源映射的目的)

没有设置改选项生成的.js.map文件:

javascript 复制代码
{"version":3,"file":"main.js","sourceRoot":"","sources":["../main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAE3B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAElB,MAAM,CAAC,IAAM,GAAG,GAAG,cAAO,CAAC,CAAC"}

设置了该选项的.js.map文件:

javascript 复制代码
{"version":3,"file":"main.js","sourceRoot":"http://codequan.com/","sources":["main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAE3B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAElB,MAAM,CAAC,IAAM,GAAG,GAAG,cAAO,CAAC,CAAC"}

inlineSourceMap

.js.map内容放进.js文件的末尾, 有助于在浏览器中调试 JavaScript 代码时,可以直接与 TypeScript 源代码进行关联,而不需要额外的 .map 文件

这些内容会以 base64 的格式嵌入.js文件

inlineSource

设置为 true,则生成的 JavaScript 文件中将包含原始 TypeScript 代码

这些内容会以 base64 的格式嵌入.js文件

declaration

设置为true时, ts 编译后会自动生成对应的.d.ts文件

declarationDir

正常情况下, 生成的.d.ts文件与编译后的.js文件在同一目录下, 通过该选项, 可以单独指定.d.ts文件的保存目录, 大部分项目都会设置为./types目录

declarationMap

类似于sourceMap, 但这个选项输出的是.d.ts文件的映射文件.d.ts.map, 该文件与.d.ts文件在同一个目录内

stripInternal

如果设置为true, ts 会在输出.d.ts文件时, 移除包含@internal的 JSDoc 注释

如果 ts 中的某个方法, 仅用于内部使用, 不需要让使用者知道内部实现细节, 可以开启这个选项, 并在方法上添加@internalJSDoc 注释

typescript 复制代码
// main.ts

/**
 * init project
 */
export function init() {}

/**
 * @internal
 * run project
 */
export function run() {}

// 使用默认值false, 生成的声明文件 main.d.ts
/**
 * init project
 */
export declare function init(): void;
/**
 * @internal
 * run project
 */
export declare function run(): void;

// 设置为true, 生成的main.d.ts文件
/**
 * init project
 */
export declare function init(): void;

noEmit

noEmit当设置为 true 时,告诉 TypeScript 编译器不生成任何输出文件(如 JavaScript 文件或声明文件),

通常用于构建工具和开发环境中,以提高编译速度或仅进行类型检查。在这种情况下,编译器仅检查 TypeScript 代码并报告错误,而不会生成实际的输出文件。

noEmitOnError

用于控制是否在发现类型错误时阻止 TypeScript 编译器生成输出文件。当将 noEmitOnError 设置为 true 时,如果 TypeScript 编译器在编译过程中发现了任何类型错误,它将不会生成编译输出文件(通常是 JavaScript 文件)。

emitDeclarationOnly

emitDeclarationOnly当设置为 true 时,告诉 TypeScript 编译器只生成声明文件(.d.ts 文件),而不生成 JavaScript 文件。这对于创建库的类型定义文件非常有用。

通常在创建库或模块的类型定义文件时使用,以确保只生成声明文件而不生成 JavaScript 文件。这允许其他开发人员在不需要实际代码的情况下使用库的类型信息。

importHelpers

ts 在对某些语法与 API 进行降级的时候, 会从tslib中自动导入相关的函数, 比如

typescript 复制代码
// main.ts
export const add = (name: string[]) => {
  return ["lily", ...name];
};
//  main.js
var __spreadArray =
  (this && this.__spreadArray) ||
  function (to, from, pack) {
    if (pack || arguments.length === 2)
      for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
          if (!ar) ar = Array.prototype.slice.call(from, 0, i);
          ar[i] = from[i];
        }
      }
    return to.concat(ar || Array.prototype.slice.call(from));
  };
export var add = function (name) {
  return __spreadArray(["lily"], name, true);
};

上面输出文件中的__spreadArray就是从tslib中导入的函数, 用来降级扩展运算符

如果该选项设为true, 告诉 ts 不自动往代码中写入__spreadArray函数, 输出内容就变成了:

javascript 复制代码
import { __spreadArray } from "tslib";
export var add = function (name) {
  return __spreadArray(["lily"], name, true);
};

这个时候, 项目中就需要提前安装好tslib库, 防止在调用__spreadArray函数式报错

noEmitHelpers

如果设置为true, TypeScript 编译器不会将任何辅助函数插入到生成的 JavaScript 代码中。这通常用于浏览器环境或其他运行时环境

上面案例中的输出文件内容就变成:

javascript 复制代码
export var add = function (name) {
  return __spreadArray(["lily"], name, true);
};

其中__spreadArray函数就要从全局上下文中获取了

downlevelIteration

用于控制是否启用针对迭代器 的 "降级" 编译。这个选项通常与 for...of 循环结合使用,因为不同版本的 JavaScript 支持不同的迭代行为。

假设有输入文件:

typescript 复制代码
const str = "Hello!";
for (const s of str) {
  console.log(s);
}

正常的"降级":

javascript 复制代码
var str = "Hello!";
for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
  var s = str_1[_i];
  console.log(s);
}

设置为true的"降级":

javascript 复制代码
var __values =
  (this && this.__values) ||
  function (o) {
    var s = typeof Symbol === "function" && Symbol.iterator,
      m = s && o[s],
      i = 0;
    if (m) return m.call(o);
    if (o && typeof o.length === "number")
      return {
        next: function () {
          if (o && i >= o.length) o = void 0;
          return { value: o && o[i++], done: !o };
        },
      };
    throw new TypeError(
      s ? "Object is not iterable." : "Symbol.iterator is not defined."
    );
  };
var e_1, _a;
var str = "Hello!";
try {
  for (
    var str_1 = __values(str), str_1_1 = str_1.next();
    !str_1_1.done;
    str_1_1 = str_1.next()
  ) {
    var s = str_1_1.value;
    console.log(s);
  }
} catch (e_1_1) {
  e_1 = { error: e_1_1 };
} finally {
  try {
    if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);
  } finally {
    if (e_1) throw e_1.error;
  }
}

一般情况下,如果目标是支持较老版本的 JavaScript 运行时环境, 才需要将 downlevelIteration设置为true,以确保 for...of 循环等迭代操作能够正确运行。

removeComments

设置为true时, 编译过程中会移除所有的注释代码

importsNotUsedAsValues

ts@5 中已弃用, 使用verbatimModuleSyntax代替

该选线用来告诉 ts 怎么处理文件中的import语句, 有三种值:

remove : 默认值, 会移除所有只导入没有使用的import语句

preserve: 会保留所有从未被使用过(值或类型)的导入语句

error : 会保留所有的import语句, 但是导入的值, 在代码中只被当做类型时, 会抛出错误, 比如:

typescript 复制代码
import { User } from "./foo"; // 这句会抛出错误, 因为User被导入后, 只被用作类型

export function init(user: User) {
  console.log("init");
}

// 不会提示错误的写法:
import type { User } from "./foo";

export function init(user: User) {
  console.log("init");
}

preserveConstEnums

设置为true时, ts 会保留Enum的原始数据, 且把枚举值内联到代码中

typescript 复制代码
// 编译前, main.ts
const enum Color {
  red = 1,
  green = 2,
  blue = 3,
}

const selectedColor = Color.red;
if (selectedColor === Color.red) {
  console.log("That is a great choice.");
}

// 默认值 false, 编译后:
var selectedColor = 1; /* Color.red */
if (selectedColor === 1 /* Color.red */) {
  console.log("That is a great choice.");
}

// 设置为true编译后 (enum被编译为一个对象来保存枚举的key和value):
var Color;
(function (Color) {
  Color[(Color["red"] = 1)] = "red";
  Color[(Color["green"] = 2)] = "green";
  Color[(Color["blue"] = 3)] = "blue";
})(Color || (Color = {}));

var selectedColor = 1; /* Color.red */
if (selectedColor === 1 /* Color.red */) {
  console.log("That is a great choice.");
}

需要注意的是isolatdModules设置为true时, 也会影响枚举的编译结果, 并把该选项的值设置为true:

javascript 复制代码
// 设置为isolatdModules: true, 编译后:
var Color;
(function (Color) {
  Color[(Color["red"] = 1)] = "red";
  Color[(Color["green"] = 2)] = "green";
  Color[(Color["blue"] = 3)] = "blue";
})(Color || (Color = {}));

var selectedColor = Color.red;
if (selectedColor === Color.red) {
  console.log("That is a great choice.");
}

通常不需要启用,除非你明确需要在运行时访问常数枚举的类型信息。默认情况下,TypeScript 会将常数枚举内联到生成的代码中,以提高性能和减小文件大小。

preserveValueImports

ts@5 版本已启用, 推荐使用verbatimModuleSyntax

在某些特殊情况下, ts 无法检测到导入的内容是否被使用, 比如:

typescript 复制代码
import { defualtUser } from "./foo";
eval("console.log(defaultUser)");

当该选项设为 true 的时候, 将强制 ts 保留这类import语句

newLine

设置输出文件的行尾类型, 有crlf(dos)lf(unix)两种值

emitBOM

该选项默认值是 false, 且通常不需要关注该选项

用于控制是否在输出文件中包含字节顺序标记(Byte Order Mark,BOM)。

设置为true时, 输出文件会包含字节顺序标记

BOM 是一个特殊的字符,通常在 Unicode 编码文件中的开头用于标识文件的编码方式。

Env,Language 环境及设置相关选项

target

用于指定编译后的 JavaScript 代码应该符合的 ECMAScript 版本

以下是 target 选项的一些常见值和它们的含义:

可用值 说明
ES3 编译为 ECMAScript 3(ES3)版本的 JavaScript。这是较旧的 ECMAScript 版本,支持在更古老的浏览器中运行。TS@5.5 版本开始可能会停用这个选项, 慎用
ES5 编译为 ECMAScript 5(ES5)版本的 JavaScript。ES5 支持较新的 JavaScript 特性,适用于现代浏览器。
ES2015(或 ES6) 编译为 ECMAScript 2015(ES2015,也称为 ES6)版本的 JavaScript。ES2015 引入了一些重要的新特性,如箭头函数、模块、类等。
ES2016 编译为 ECMAScript 2016(ES2016)版本的 JavaScript。ES2016 引入了一些小的语言改进。
ES2017 编译为 ECMAScript 2017(ES2017)版本的 JavaScript。ES2017 引入了异步函数等功能。
ESNext 编译为最新的 ECMAScript 标准(通常是草案或未来标准的一部分)。这意味着使用最新的 JavaScript 特性,但可能不适用于所有 JavaScript 运行时。

选择适当的 target 取决于你的目标环境。如果代码将在现代浏览器中运行,通常可以选择 ES6(ES2015)或更高版本。如果需要支持较老的浏览器或特定的 JavaScript 运行时,可能需要选择较低的版本。

ES5为例, 可以看到语法中的const被改为var; 箭头函数被改为function; 模板字符串也被转为字符串拼接:

typescript 复制代码
// tsconfig.json
{
  "files": [
    "main.ts",
  ],
  "compilerOptions": {
    "module": "ESNext",
    "target": "ES5",
  }
}

// 编译前
export function init() {
  const a = 1;
  const b = () => {};
  const c = `${a}=1`;
}

// 编译后
export function init() {
    var a = 1;
    var b = function () { };
    var c = "".concat(a, "=1");
}

lib

ts 内置了一套和 JS 相匹配的类型库, 比如 JS 的Math,Navigator,或者浏览器的Window,Document等, 该选项决定了 TypeScript 编译器应该为你的代码提供哪些类型定义和内置对象的支持,以帮助你进行类型检查和开发时的提示

选项的值是一个string[]类型, 可用值包括ES5,ES2015,ES6,ES2016等一系列值, 还可以添加某些单独的库组件,比如DOM.Iterable,ES2015.Generator等,完整的清单可以查看 ts 的lib 库文件

lib选项可以与target组合使用: 设置target选项, 会修改lib选项的默认值, lib选项则可以在target包含的类型库之外额外添加一些类型库

javascript 复制代码
// tsconfig.js
{
  "files": [
    "main.ts",
  ],
  "compilerOptions": {
    "module": "ESNext",
    "target": "ES5",
    "lib": [
      "ESNext" //  如果没有这个选项, 下面main.ts中的Promise会抛出异常, 因为target:ES5中不包含Promise相关的API, ts就无法识别Promise
    ]
  }
}

// main.ts
export function init() {
  return new Promise((res) => {
    res({});
  });
}

noLib

用于禁用默认的 TypeScript 类型库(lib)的引入。当你设置 noLib 为 true 时,TypeScript 将不会自动包含默认的类型库,包括 ES6、DOM 和其他内置类型。

这个选项通常用于特殊情况,例如,当你希望完全自定义哪些类型库应该包含在你的项目中,而不希望 TypeScript 自动引入默认的类型库。

禁用默认类型库可能会导致你在编写代码时缺少一些常见的类型定义,因此在绝大多数项目中,不建议启用 noLib。通常情况下,建议使用默认的 TypeScript 类型库,以便充分利用 TypeScript 的类型检查和提示功能。

experimentalDecorators

启用装饰器功能

emitDecoratorMetadata

设置为true时, ts 会把被装饰器装饰的元数据信息保存到输出的.js文件中

经实测,只有class method class method params的信息会被保存,class本身没有元数据, 不会被存储

typescript 复制代码
// 编译前 main.ts

// 未启用该选项编译后:
var __decorate =
  (this && this.__decorate) ||
  function (decorators, target, key, desc) {
    var c = arguments.length,
      r =
        c < 3
          ? target
          : desc === null
          ? (desc = Object.getOwnPropertyDescriptor(target, key))
          : desc,
      d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
      r = Reflect.decorate(decorators, target, key, desc);
    else
      for (var i = decorators.length - 1; i >= 0; i--)
        if ((d = decorators[i]))
          r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
function LogMethod(target, propertyKey, descriptor) {
  console.log(target);
  console.log(propertyKey);
  console.log(descriptor);
}
class Demo {
  foo(bar) {
    // do nothing
  }
}
__decorate([LogMethod], Demo.prototype, "foo", null);
const demo = new Demo();

// 启用该选项编译后:
var __decorate =
  (this && this.__decorate) ||
  function (decorators, target, key, desc) {
    var c = arguments.length,
      r =
        c < 3
          ? target
          : desc === null
          ? (desc = Object.getOwnPropertyDescriptor(target, key))
          : desc,
      d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
      r = Reflect.decorate(decorators, target, key, desc);
    else
      for (var i = decorators.length - 1; i >= 0; i--)
        if ((d = decorators[i]))
          r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
var __metadata =
  (this && this.__metadata) ||
  function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
      return Reflect.metadata(k, v);
  };
function LogMethod(target, propertyKey, descriptor) {
  console.log(target);
  console.log(propertyKey);
  console.log(descriptor);
}
class Demo {
  foo(bar) {
    // do nothing
  }
}
__decorate(
  [
    LogMethod,
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Number]),
    __metadata("design:returntype", void 0),
  ],
  Demo.prototype,
  "foo",
  null
);
const demo = new Demo();

jsx

允许在 ts 中使用 jsx 语法

在 ts 中启用 jsx 语法, 需要安装react react-dom @types/react @types/react-dom模块, 且必须在入口文件中引入import React from 'react'

jsx 的值只允许以下几种:

typescript 复制代码
// main.tsx
import React from "react";

export const HelloWorld = () => <h1>Hello world</h1>;
javascript 复制代码
// react 默认值, jsx语法会被替换为React.createElement函数
import React from "react";
export const HelloWorld = () => React.createElement("h1", null, "Hello world");

// react-jsx  指定使用 react/jsx-runtime.js 文件(在 node_modules/react 内)中的函数解析 jsx
import { jsx as _jsx } from "react/jsx-runtime";
export const HelloWorld = () => _jsx("h1", { children: "Hello world" });

// react-jsxdev 指定使用 react/jsx-dev-runtime.js 文件(在 node_modules/react 内)中的函数解析 jsx
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
const _jsxFileName =
  "/Users/loki/Documents/office/aprojects/zhongke/vary-ui/ts/main.tsx";
export const HelloWorld = () =>
  _jsxDEV(
    "h1",
    { children: "Hello world" },
    void 0,
    false,
    { fileName: _jsxFileName, lineNumber: 3, columnNumber: 32 },
    this
  );

// preserve  保留源代码, 不做任何处理, 输出 .jsx 文件
import React from "react";
export const HelloWorld = () => <h1>Hello world</h1>;

// react-native  保留原代码, 不做任何处理, 但输出 .js 文件
import React from "react";
export const HelloWorld = () => <h1>Hello world</h1>;

reactNamespace

已被废弃, 使用新的选项jsxFactory代替. 使用自定义或第三方的解析函数, 替换React.createElement

jsxFactory

如果 tsx 中的 jsx 内容不想使用React.createElement来解析, 想使用自定义或者第三方的解析函数, 该选项用来指定替换React.createElement的函数名

比如, 有的项目会使用preact中的h函数来代替React.createElement:

typescript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
  }
}

// main.tsx
import {h} from 'preact'
export const HelloWorld = () => <h1>Hello world</h1>;


// 编译后的 main.js, 这里的 h 代替了 React.createElement
import { h } from 'preact';
export const HelloWorld = () => h("h1", null, "Hello world");

jsxFragmentFactory

该选项是为了适配 React18 中引入的新特性Fragment新增的, 如果在项目中想使用自定义的或者第三方的 jsx 片段构造函数, 可以使用该选项来设置 jsx 片段构造函数的名称;

比如, 使用 preact提供的Fragment来代替React.Fragment:

先看看使用react的情况:

typescript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react",
  }
}

// main.tsx
import React from 'react'

export const HelloWorld = () => <><h1>Hello world</h1></>;


// main.js
import React from 'react';
export const HelloWorld = () => React.createElement(React.Fragment, null,
    React.createElement("h1", null, "Hello world"));

再看看使用preact替换 jsx 片段构造函数的:

typescript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",
  }
}

// main.tsx
import { h, Fragment } from "preact";

export const HelloWorld = () => (
  <>
    <h1>Hello world</h1>
  </>
);

// main.js
// 这里React.createElement被preact的h函数替换, React.Fragment被preact.Fragment替换
import { h, Fragment } from 'preact';
export const HelloWorld = () => h(Fragment, null,
    h("h1", null, "Hello world"));

需要注意的是, 该选项, 必须与jsxFactory搭配使用, 不能单独设置

jsxImportSource

jsx选项设置为react-jsx或者react-jsxdev时, 该选项用来从自定义或者第三方的模块中导入 JSX 标识符

比如:

typescript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
  }
}

// main.tsx
import React from "react";

export const HelloWorld = () => (
  <>
    <h1>Hello world</h1>
  </>
);

// main.js  这里jsx, Fragment都是从"react/jsx-runtime"导入的
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
export const HelloWorld = () => _jsx(_Fragment, { children: _jsx("h1", { children: "Hello world" }) });

如果使用preact模块作为导入来源时:

typescript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "preact"
  }
}


// main.js  这里jsx, Fragment都是从"preact/jsx-runtime"导入的, 其他都没有变化
import { jsx as _jsx, Fragment as _Fragment } from "preact/jsx-runtime";
export const HelloWorld = () => _jsx(_Fragment, { children: _jsx("h1", { children: "Hello world" }) });

moduleDetection

该选项用来控制 ts 如何识别某个文件是不是 module, ts 对模块的分辨逻辑可以参考官方文档

该选项有三种值:

auto : 默认值, 当module选项设置为Node16或者NodeNext时, ts 不仅通过**文件中是否有顶级的 export或者import**来识别模块, 还会通过package.json文件中的type字段是否为module来识别模块; 如果jsx选项被设置为react-jsx, ts 还会根据被导入文件的后缀是不是.jsx或者.tsx来识别模块

legacy : ts@4.6 及之前版本的默认值, 表示 ts 只通过**文件中是否有顶级的 export或者import**来识别模块

force :把所有非.d.ts等声明文件都视为模块

暂不清楚该选项的使用场景

useDefineForClassFields

ES2022 版本开始, 可以在Class中以下面的方式添加类本身的属性:

javascript 复制代码
// ES2022版本之前
class C {
  constructor() {
    this.foo = 100;
  }
}

// ES2022版本之后的 Class Fields语法
class C {
  foo = 100;
}

这种写法允许在类中直接定义实例字段而不需要在构造函数中进行初始化。这提供了更简洁的语法来定义类的属性。

该选项告诉 ts 生成的代码中是否允许使用Class fields语法

target被设置为**ES2022及以上**的值是, 该选项自动设置为true, 否则就自动设置为false

通常情况下, 该选项不需要人为设置

Modules 模块解析相关选项

module

用于设置编译后输出文件 的(模块)类型,可以不设置, 默认值是commonjs

假如你有这样一个文件(官方案例):

typescript 复制代码
// @filename: index.ts
import { valueOfPi } from "./constants";

export const twoPi = valueOfPi * 2;

module的可用值以及输出格式有以下选项:

javascript 复制代码
// CommonJS
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
const constants_1 = require("./constants");
exports.twoPi = constants_1.valueOfPi * 2;

// amd
define(["require", "exports", "./constants"], function (
  require,
  exports,
  constants_1
) {
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.twoPi = void 0;
  exports.twoPi = constants_1.valueOfPi * 2;
});

// umd
(function (factory) {
  if (typeof module === "object" && typeof module.exports === "object") {
    var v = factory(require, exports);
    if (v !== undefined) module.exports = v;
  } else if (typeof define === "function" && define.amd) {
    define(["require", "exports", "./constants"], factory);
  }
})(function (require, exports) {
  "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.twoPi = void 0;
  const constants_1 = require("./constants");
  exports.twoPi = constants_1.valueOfPi * 2;
});

// system
System.register(["./constants"], function (exports_1, context_1) {
  "use strict";
  var constants_1, twoPi;
  var __moduleName = context_1 && context_1.id;
  return {
    setters: [
      function (constants_1_1) {
        constants_1 = constants_1_1;
      },
    ],
    execute: function () {
      exports_1("twoPi", (twoPi = constants_1.valueOfPi * 2));
    },
  };
});

// es6 | es2015 | es2020 | es2022
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;

// node16 | nodenext

//

上面node16 | nodenext 没有给出具体的格式案例, 是以为从 ts@4.7 开始 node16 与 nodenext 输出的格式取决于文件扩展名与 package.json 文件中的 type 字段:

条件 输出格式
package.json.type: "module" esm 格式
package.json.type: "commonjs" CommonJS 格式
文件扩展名: .mjs或者.mts esm 格式
文件扩展名: .cjs或者.mts CommonJS 格式

moduleResolution

用于设置模块的解析策略, 与module搭配使用, 有以下几种选项

  • Classic: 是 ts@1.6 之前版本的默认值, 现在保留这种策略主要是为了向后兼容, 现在基本上用不到这个选项了, 除非需要与特殊的模块配合使用

  • Node: 指的是模仿 NodeJS的模块路径解析模式来查找文件, 可与module选项任意值搭配使用

  • Node10: 与Node相同, 是 ts@5.2.2 中Node的别名

  • Node16: 必须"module": "Node16"配合使用, 不同的是, 生成的文件中,会保留文件中ES6+中的新语法(const,let,箭头函数等)

  • NodeNext: 必须"module":"NodeNext"配合使用, 其他与Node16相同

  • Bundler: 要求module选项的值必须ESM类(以ES开头)的值, 生成的文件也是是ES模块

ClassicNode两种解析方式的不同之处可以直接参考官方文档; 这里只说 ts 中的node解析模式:

moduleSuffixes

该选项用来覆盖解析模块时要搜索的默认文件名后缀列表

假设有以下配置和文件

typescript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "moduleSuffixes": [".ios", ".native", ""]
  }
}

// main.ts
import * as foo from "./foo";

ts 将会查找./foo.ios.ts,./foo.native.ts,./foo.ts

此选项多用于 React Native 项目

需要注意的是"moduleSuffixes": [".ios", ".native", ""]中有一个"", 这是不可缺少的, 没有它, ts 就不会查找./foo.ts

baseUrl

该选项主要用于告诉 ts 在相对于哪个目录解析非相对路径模块

如果选项值是一个相对路径, 则根据tsconfig.json所在位置计算

typescript 复制代码
// /a.ts
export function init() {
  console.log("./a");
}

// /src/a.ts
export function init() {
  console.log("./src/a");
}


// /main.ts
import { init } from "a"; // 这里的 "a" 会被解析到 src/a.ts

export function foo() {
  init();
}

// tsconfig.json
{
  "files": [
    "main.ts",
  ],
  "include": [
    "*/src/**/*.ts"
  ],
  "compilerOptions": {
    "baseUrl": "./src",
  }
}

paths

用于定义模块导入路径的别名。通过使用 paths 选项,可以将特定的导入路径映射到不同的实际文件路径,从而使导入更灵活和可配置。这对于管理模块的路径和重定向导入非常有用

path的值是相对于baseUrl来解析的, 把上面的案例改一下:

typescript 复制代码
// /a.ts
export function init() {
  console.log("./a");
}

// /src/a.ts
export function init() {
  console.log("./src/a");
}

// /lib/a.ts
export function init() {
  console.log("./lib/a");
}


// /main.ts
import { init } from "a"; // 这里的 "a" 会被解析到 lib/a.ts

export function foo() {
  init();
}

// tsconfig.json
{
  "files": [
    "main.ts",
  ],
  "include": [
    "*/src/**/*.ts"
  ],
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "a": [
        "../lib/a.ts"
      ]
    }
  }
}

在平时比较常见的配置:

javascript 复制代码
{
  "compilerOptions": {
    "baseUrl": "./src",
    "path": {
      "@app/*":['../app'],
      "@lib/*":['../lib'],
    }
  }
}

所以paths的权重要高于baseUrl的权重

noResolve

用于控制是否启用 TypeScript 编译器的模块解析(module resolution)功能。当将 noResolve 设置为 true 时,它会告诉编译器不要执行模块解析,也就是不要查找和加载模块的依赖关系

通常情况下,不太需要显式地设置 noResolve 选项,因为 TypeScript 编译器会自动执行模块解析以查找和加载依赖的模块。但在一些情况下,可能会需要手动控制模块解析的过程,这时可以考虑使用 noResolve。

在某些情况下,如果知道项目中没有模块依赖关系需要解析,可以将 noResolve 设置为 true 以加快编译速度

customConditions

ts 在模拟 nodejs 的模块解析功能时, 如果模块来自node_modules, ts 会从模块的package.json.exports属性中读取文件, customConditions用于使用自定义导出条件

需要注意的是: package.json.exports属性只有package.json.typemodule时才有效, 所以customConditions选项也是有条件的:

Option 'customConditions' can only be used when 'moduleResolution' is set to 'node16', 'nodenext', or 'bundler')

resolveJsonModule

默认值false, 设置为true时, 允许导入扩展名为 .json 的模块,这是项目中的常见做法。这包括根据静态 JSON 形状生成导入类型

resolvePackageJsonImports

当从一个文件导入以#开头的value或者type时, 如果这个文件所在的目录(或者祖先目录)内有一个package.json文件, 开启这个选项会强制 ts 从package.json.imports字段确认导入的实际文件

moduleResolution设置以为Node16,NodeNext,Bundler时, 该选项的默认值自动设置为true

暂不清楚该选项的使用场景

resolvePackageJsonExports

主要用于处理 package.json 文件中的 exports 字段,以更好地支持导入不同版本的 JavaScript 模块

moduleResolution设置以为Node16,NodeNext,Bundler时, 该选项的默认值自动设置为true

暂不清楚该选项的使用场景

allowArbitraryExtensions

正常情况下, ts 不允许在文件中导入.ts或者.tsx文件, 只允许使用标准的 js 文件扩展名.js或者.jsx

如果在 ts 文件中导入了非正常扩展名的文件, 需要像下面这样添加一个对应的.d.ts文件明确告诉 ts 该文件的类型:

typescript 复制代码
// main.js
import css from 'app.css'

console.log(css.mainColor)


// app.css
.mainColor{
  color: red
}

// app.css.d.ts
declare const css: {
  mainColor: string
}

我启用了allowArbitraryExtensions后,没啥反应

allowImportingTsExtensions

启用该选项时, 允许在导入.ts, .mts,或者.tsx文件时省略文件后缀, 但是只有当noEmit或者emitDeclarationOnly启用时, 这个选项才能开启

ts@5.2.2 中这个选项默认值应该是true, 因为我没有启用它, ts 也没有对省略后缀的语句报错

allowUmdGlobalAccess

暂不清楚使用场景

rootDir

rootDirs

types 与 typeRoot

当项目中引入了一个第三方的库, 且该库没有提供官方的类型声明文件时, ts 不会报错, 但会做如下处理:

typescript 复制代码
// main.ts
import { init } from "foo";
// 上面的语句会提示: 无法找到模块"foo"的声明文件。"/Users/loki/Documents/office/aprojects/zhongke/vary-ui/ts/node_modules/foo/index.js"隐式拥有 "any" 类型

export function initMain() {
  console.log(init);
}

这种情况下, 通常需要我们手动给模块foo添加一个类型声明文件, 以支持 ts 进行类型检查或者支持编辑器自动识别类型

其中typeRoots用来告诉 ts 自定义类型声明文件所在的目录位置,

types用来告诉 ts 要加载的类型声明文件名称

像上面的案例, 我们可以添加如下配置:

typescript 复制代码
// tsconfig.json
{
  compilerOptions:{
    "typeRoots": [
      // 假设自定义类型声明文件都放在./customer-types目录内
      "./customer-types"
    ],
    "types": [
      "foo" // 告诉ts加载目录内的 foo.d.ts 文件
    ],
  }
}

// ./customer-types/foo.d.ts
declare module "foo" {
  export function init(): void;
}

还有一种使用场景是, 假设你的项目中使用了一个全局变量:

typescript 复制代码
// main.ts
export function initMain() {
  console.log(globalConfig.env);
}

可以添加下面的配置解决这个问题:

typescript 复制代码
// tsconfig.json
{
  compilerOptions:{
    "typeRoots": [
      // 假设自定义类型声明文件都放在./customer-types目录内
      "./customer-types"
    ],
    "types": [
      "index" // 告诉ts加载目录内的 index.d.ts 文件
    ],
  }
}

// ./customer-types/index.d.ts
declare var globalConfig: {
  env: string;
};

typeChecking 类型检查相关选项

alwaysStrict

alwaysStrict用来控制生成的 JS 文件 具有use strict标记, 该行为让生成的 js 文件以严格模式执行

strict

strict则是用来控制 ts 在编译过程中对 ts 文件中某些行为的处理 , 它包含了一系列的选项: strictNullChecks,strictBindCallApply,strictFunctionTypes,noImplicitAny,noImplicitThis,strictPropertyInitialization,useUnknownInCatchVariables等, 如果strict设为 true, 则这些选项都会被启用

也可以在stricttrue的情况下, 单独关闭某些选项, 像这样:

json 复制代码
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": false
  }
}

strict是一系列选项的集合, 它包含的选项可能会随着 ts 版本的升级而变化

strictNullChecks

如果设置为true, 下面这段代码在 ts 编译是会产生编译错误, 因为loggedInUser的值可能是null

typescript 复制代码
declare const loggedInUsername: string;

const users = [
  { name: "Oby", age: 12 },
  { name: "Heera", age: 32 },
];

const loggedInUser = users.find((u) => u.name === loggedInUsername);
console.log(loggedInUser.age); // 编译错误

strictBindCallApply

设置为true后, ts 将会检查使用call,bind,apply调用函数时,参数的传递情况, 比如下面的案例中, ts 会产生编译错误, 因为函数fn需要的是字符串类型的参数

typescript 复制代码
// With strictBindCallApply on
function fn(x: string) {
  return parseInt(x);
}

const n1 = fn.call(undefined, "10");

const n2 = fn.call(undefined, false); // Argument of type 'boolean' is not assignable to parameter of type 'string'.

strictFunctionTypes

设置为true时, 会对函数参数启用更严格的检查, 下面的案例就会产生编译错误,因为函数func的类型与函数fn的参数类型并不相同, 所以不能直接赋值

typescript 复制代码
function fn(x: string) {
  console.log("Hello, " + x.toLowerCase());
}

type StringOrNumberFunc = (ns: string | number) => void;

let func: StringOrNumberFunc = fn;
// Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'.
//   Types of parameters 'x' and 'ns' are incompatible.
//     Type 'string | number' is not assignable to type 'string'.
//       Type 'number' is not assignable to type 'string'.

noImplicitAny

设置为true时, 如果函数参数没有指定类型, ts 会产生编译错误, 比如下面的案例中参数s没有指定类型,

typescript 复制代码
function fn(s) {
  // Parameter 's' implicitly has an 'any' type.
  console.log(s.subtr(3));
}

noImplicitThis

设置为true时, 用于控制是否允许在函数中使用不明确的 this 上下文,除非进行了明确的指定。这个选项可以帮助防止 this 上下文的潜在错误,特别是在面向对象编程和事件处理等情况下。它促使开发人员更加谨慎地处理 this 上下文,从而提高代码的可读性和类型安全性。

下面的代码中, this就是一个不明确的上下文, 如果想修复这个问题, 可以把函数改为箭头函数,或者手动给this指定明确的类型

typescript 复制代码
function logMessage(message: string) {
  console.log(this); // Error: 'this' implicitly has type 'any'
  console.log(message);
}

const obj = {
  name: "John",
  log: logMessage,
};

obj.log("Hello, TypeScript!");

strictPropertyInitialization

当设置为 true 时,TypeScript 编译器会要求类中的属性必须在构造函数中进行初始化或者在属性声明时提供初始值。如果没有满足这些条件,编译器会产生一个错误,表示属性可能处于未定义的状态,这有助于避免在运行时出现未定义属性的错误

在下面的示例中,由于属性 name 声明的时候没有初始化值, 又没在构造函数中赋值,TypeScript 会产生一个错误,指出属性 name可能处于未定义的状态

typescript 复制代码
class Person {
  name: string; // Error: Property 'name' has no initializer and is not definitely assigned in the constructor.
}

const person = new Person();
console.log(person.name); // Potential runtime error: 'name' is undefined

useUnknownInCatchVariables

TypeScript 4.0 版本引入的一个编译器选项

当设置为 true 时,TypeScript 会将 catch 子句中的异常变量的类型隐式推断为unknown。这意味着在catch子句中,异常变量将被视为具有unknown类型,需要显式进行类型检查或类型断言才能使用它们。

在下面的示例中,error未指明类型, error.message在运行时可能会报错,

typescript 复制代码
try {
  // 一些可能抛出异常的操作
} catch (error) {
  // 在useUnknownInCatchVariables默认情况下,error 被推断为 any 类型
  console.log(error.message); // ts编译不会报错,但可能在运行时出错
}

如果把useUnknownInCatchVariables设置为true, error会被隐式推断为unknown类型, unknown类型的error是不允许任何操作的, 所以在编译过程中, ts 会产生编译错误

allowUnreachableCode

默认值 false, 用于控制是否允许编写包含不可达代码(unreachable code)的 TypeScript 文件。不可达代码是指永远不会被执行到的代码,它通常是错误或者不必要的。

比如下面的代码中:

javascript 复制代码
function divide(a: number, b: number): number {
  if (b === 0) {
    return Infinity;
  }
  return a / b;
  console.log("This line is unreachable"); // 不可达代码
}

ts 在编译这段代码的时候, 就会产生一个编译错误

这种 unreachable 代码会导致代码不清晰, 所以尽量保持它为true

allowUnusedLabels

用于控制是否允许在代码中定义但未使用的标签(labels)。标签通常与循环(如 for、while)和 break 或 continue 语句一起使用,用于跳出或跳转到指定的代码块。

设为true的时候可以允许未使用的标签存在,而不会产生编译错误

通常情况下,建议将 allowUnusedLabels 保持为默认值 false,以确保代码的清晰性和可维护性。未使用的标签通常是代码中的无用元素,可能会使代码更难以理解。

typescript 复制代码
// 在默认情况下,未使用的标签会导致编译错误
label1: for (let i = 0; i < 3; i++) {
  console.log(i);
}

// 如果启用了 allowUnusedLabels,将不会产生编译错误
label2: for (let i = 0; i < 3; i++) {
  console.log(i);
}

exactOptionalPropertyTypes

在默认值false的时候, 下面的代码中, color可以被设置为三种值: dark,light,或者undefined, 在项目运行时color is not definedcolor=undefined是两个不同的概念,

设置为true时, 下面的代码会产生编译错误, 因为 ts 将不会允许把undefined赋值给color

typescript 复制代码
interface UserDefaults {
  color?: "dark" | "light";
}

const user: UserDefaults = {};

user.color = undefined; // Error: 类型 "undefined" 不能分配给"exactOptionalPropertyTypes: true"的类型 ""dark" | "light""。请考虑将 "undefined" 添加到目标类型。

noFallthroughCasesInSwitch

设置为true时, ts 会检查switch case中的case语句中是否包含break,continue,return, 如果没有包含, ts 会产生编译错误. 启用 noFallthroughCasesInSwitch 选项有助于防止在 switch 语句中不经意地出现 fallthrough 的情况,从而提高代码的可维护性和可读性。这对于确保每个 case 都是明确且独立的情况下非常有用。

typescript 复制代码
// 在默认值false的时候,不带 break 的 case 是合法的, 设为true后, ts会报错
function getResult(option: string): number {
  let result = 0;
  switch (option) {
    case "A":
      result += 10;
    // 没有 break,流入到下一个 case
    case "B":
      result += 20;
      break;
    case "C":
      result += 30;
      break;
  }
  return result;
}

noImplicitOverride

默认值为false时,下面的代码中是不会产生编译异常的, 如果设为true, animal.speak();会产生编译异常. 因为此时 TypeScript 编译器会要求子类中对父类的成员进行重写时,必须使用 override 关键字明确指定

该选项有助于确保子类正确地重写了父类的成员,从而提高代码的类型安全性。这对于维护大型项目和确保正确的多态行为非常有用

typescript 复制代码
class Animal {
  speak() {
    console.log("Animal speaks");
  }
}

class Dog extends Animal {
  speak() {
    console.log("Dog barks");
  }
}

// 如果启用了 noImplicitOverride,下面的代码将会产生错误
const animal: Animal = new Dog();
animal.speak(); // Error: Property 'speak' in type 'Animal' is not assignable to the same property in base type 'Dog'.

noImplicitReturns

当设置为 true 时,TypeScript 编译器会要求函数内部的所有代码路径都必须具有明确的返回语句或返回类型。如果设置为 false(默认值),则不会强制要求明确的返回。

该选项有助于确保函数内部的所有代码路径都具有明确的返回语句或返回类型,从而提高代码的类型安全性。这对于防止潜在的运行时错误和类型不一致问题非常有用。

typescript 复制代码
// 在默认情况下,不要求明确的返回
function add(a: number, b: number): number {
  if (a && b) {
    return a + b;
  }
  // 缺少明确的返回语句,但不会产生编译错误
}

// 如果启用了 noImplicitReturns,下面的代码将会产生错误
function subtract(a: number, b: number): number {
  if (a && b) {
    return a - b;
  }
  // Error: Function lacks ending return statement and return type does not include 'undefined'.
}

noPropertyAccessFromIndexSignature

当设置为 true 时,TypeScript 编译器会禁止通过索引签名访问没有明确声明的属性

该选项有助于防止在代码中意外访问未明确声明的属性,从而提高代码的类型安全性。这对于确保对象属性的类型安全性非常有用。

typescript 复制代码
interface MyDictionary {
  [key: string]: string;
}

const dictionary: MyDictionary = {
  apple: "fruit",
  car: "vehicle",
};

// 如果启用了 noPropertyAccessFromIndexSignature,下面的代码将会产生错误
const fruit = dictionary.apple; // Error: Element implicitly has an 'any' type because index expression is not of type 'number'.

noUncheckedIndexedAccess

当设置为 true 时,TypeScript 编译器会要求在索引操作中明确处理 nullundefined 检查。这意味着在访问数组元素或对象属性之前,必须先确保索引不为 nullundefined,或者使用可选链式操作符 ?. 进行安全访问。

typescript 复制代码
// 在默认情况下,允许省略 null 和 undefined 检查
function getElement(arr: string[], index: number): string {
  return arr[index]; // 没有 null 或 undefined 检查
}

const myArray: string[] = ["apple", "banana", "cherry"];
const result = getElement(myArray, 3); // 不会产生编译错误,但可能在运行时出错

// 如果启用了 noUncheckedIndexedAccess,下面的代码将会产生错误
// const result = getElement(myArray, 3); // Error: Object is possibly 'undefined'.

如果启用了这个检查, 上面的代码必须以下面的任意一种方式处理(这两种方式都要求在返回值中添加| undefined类型):

第一种方式:

typescript 复制代码
// 使用可选链式操作符
function getElement(arr: string[], index: number): string | undefined {
  return arr[index]?.toString();
}

const myArray: string[] = ["apple", "banana", "cherry"];
const result = getElement(myArray, 3); // 不会产生编译错误,result 为 undefined

第二种方式

typescript 复制代码
// 手动检查索引
function getElement(arr: string[], index: number): string | undefined {
  if (index >= 0 && index < arr.length) {
    return arr[index];
  }
  return undefined;
}

const myArray: string[] = ["apple", "banana", "cherry"];
const result = getElement(myArray, 3); // 不会产生编译错误,result 为 undefined

noUnusedLocals

noUnusedLocals设置为true时, ts 会检查代码中未使用的变量, 并在编译过程中产生编译错误, 比如下面的案例:

typescript 复制代码
const createKeyboard = (modelID: number) => {
  const defaultModelID = 23;
  // Error: 'defaultModelID' is declared but its value is never read.
  return { type: "keyboard", modelID };
};

noUnusedParameters

noUnusedParameters设置为true时, ts 会检查函数中未使用的参数, 并在编译过程中产生编译错误, 比如项目的案例:

typescript 复制代码
const createDefaultKeyboard = (modelID: number) => {
  // Error: 'modelID' is declared but its value is never read.
  const defaultModelID = 23;
  return { type: "keyboard", modelID: defaultModelID };
};

JS 相关选项

allowJs

该选项设置为true后, 允许在.ts文件中引入.js文件

在 ts@5.2.2 版本测试时, 引入.js文件时编译没有抛出异常

checkJs

该选项设置为true后, ts 将会检查.js文件中的语法错误

比如:

javascript 复制代码
// 这里会抛出异常, 因为parseFloat 仅接受一个字符串作为参数
module.exports.pi = parseFloat(3.124);

Editor 编辑器相关选项

disableSizeLimit

ts 默认有一个内存使用上限, 来避免处理项目时内存使用量过高, 当项目确实比较大时, 该选项可以取消这个内存使用上限

javascript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "disableSizeLimit": "true"
  }
}

plugins

这个选项用来配置一些基于 ts 的插件, 常用于编辑器中的语法高亮等功能

比如 NodeJS 项目中可能需要写一些 SQL 语句, ts-sql-plugin插件就可以提供 SQL 语法高亮的功能

再比如typescript-styled-plugin插件可以为 ts 中的 CSS 样式内容提供语法高亮功能

Interop Constraints 互相操作约束(针对 CommonJS 模块)

allowSyntheticDefaultImports

用于控制在导入 CommonJS 模块时是否允许合成默认导出(synthetic default imports)

在该选项开启的模式下, 假设你有一个 commonjs 的模块:

typescript 复制代码
// src/foo.js
exports.init = "foo init";

// src/foo.d.ts
export const init: string;

// main.ts
import foo from "foo";

上面的./src/foo.js中没有exports.default(没有默认导出), 但allowSyntheticDefaultImports选项让 ts 对该文件进行了合成默认导出操作, 所以不会抛出错误

如果把该选项设置为false, ts 会报错:

typescript 复制代码
// tsconfig.json
{
  "compilerOptions": {
    "allowSyntheticDefaultImports": false
  }
}

// main.ts
import foo from "foo"; // Error: 模块""/Users/loki/Documents/office/aprojects/zhongke/vary-ui/ts/src/foo""没有默认导出。

esModuleInterop

该选项用于控制在导入 CommonJS 模块(通常是 Node.js 模块)时是否启用额外的互操作性特性;

module选项设置为Node16或者NodeNext时, 该选项自动设置为true, 否则设置为false

目前没有发现启用该选项到底有什么优势, 也不清楚引入该选项的出发点是什么, 下面只说启用该选项与未启用该选项编译结果的不同

启用该选项时, 会自动启用allowSyntheticDefaultImports选项

举个例子, 假设有这么一个模块foo:

typescript 复制代码
// node_modules/foo/index.js
exports.init = "foo init";
exports.default = "default";

// node_modules/foo/index.d.js
export const init: string;
export default init;

// tsconfig.json
{
  "compilerOptions": {
    "module": "CommonJS",
    "target": "ES5",
    "moduleResolution": "Node10",
  }
}

如果想在main.ts中导入foo中的默认导出, 或者具名导出, 必须这样写:

typescript 复制代码
// main.ts
import * as foo from "foo"; // 第一种引用方式
console.log(foo);

// 第一种编译后 main.js
("use strict");
Object.defineProperty(exports, "__esModule", { value: true });
var foo = require("foo");
console.log(foo); // { init: 'foo init', default: 'default' }

/* ---------------------------*/

// main.ts
import foo from "foo"; // 第二种引用方式
console.log(foo);

// 第二种编译后 main.js
("use strict");
Object.defineProperty(exports, "__esModule", { value: true });
var foo_1 = require("foo");
console.log(foo_1.default); // 'default'

这两种写法输出结果不同的原因从输出文件就可以看出来: 是因为在 ts 中, 命名导入语句import * as foo from "foo"被处理成const foo = require("foo") , 默认导入语句import foo from "foo"被处理成const foo = require("foo").default

ts 这样处理的原因是: 在 ES6 规范中,import * as foo from "foo"指的是用来导入"foo"模块内的全部导出export xxx; 而import foo from "foo"指的是用来导入"foo"模块的默认导出export default

如果把该选项设置为true, 会统一这两种导入方式的过程, 下面是启用该选项后, 两种不同方式的编译结果:

javascript 复制代码
// 采用 import foo from "foo" 的编译结果:
"use strict";
var __importDefault =
  (this && this.__importDefault) ||
  function (mod) {
    return mod && mod.__esModule ? mod : { default: mod };
  };
Object.defineProperty(exports, "__esModule", { value: true });
var foo_1 = __importDefault(require("foo"));
console.log(foo_1.default);

// 采用 import * as foo from "foo" 的编译结果:
("use strict");
var __createBinding =
  (this && this.__createBinding) ||
  (Object.create
    ? function (o, m, k, k2) {
        if (k2 === undefined) k2 = k;
        var desc = Object.getOwnPropertyDescriptor(m, k);
        if (
          !desc ||
          ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)
        ) {
          desc = {
            enumerable: true,
            get: function () {
              return m[k];
            },
          };
        }
        Object.defineProperty(o, k2, desc);
      }
    : function (o, m, k, k2) {
        if (k2 === undefined) k2 = k;
        o[k2] = m[k];
      });
var __setModuleDefault =
  (this && this.__setModuleDefault) ||
  (Object.create
    ? function (o, v) {
        Object.defineProperty(o, "default", { enumerable: true, value: v });
      }
    : function (o, v) {
        o["default"] = v;
      });
var __importStar =
  (this && this.__importStar) ||
  function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null)
      for (var k in mod)
        if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k))
          __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
  };
Object.defineProperty(exports, "__esModule", { value: true });
var foo = __importStar(require("foo"));
console.log(foo);

// 采用 import foo from "foo" 的输出结果      { init: 'foo init', default: 'default' }
// 采用 import * as foo from "foo" 的输出结果 { init: [Getter], default: { init: 'foo init', default: 'default' } }

可以看到, 启用该选项后, 经过 ts 的特殊处理, 这两种导入方式输出的结果是"基本一致"的

forceConsistentCasingInFileNames

默认是true, 用于控制文件名的一致性检查。该选项会影响 TypeScript 编译器对文件名的大小写一致性进行强制检查

这个选项的主要目的是确保在不同的操作系统和文件系统上使用 TypeScript 时,文件名的大小写一致性,从而减少由于文件名大小写不一致引起的问题

不推荐关闭这个选项, 如果开发人员 A 在区分大小写的文件系统中工作而开发人员 B 则在不区分大小写的文件系统中工作,这可能出现问题

isolatedModules

tsc 在编译时, 可以依赖这个项目的所有文件,正确的分辨出import语句中,哪些是type value哪些是pure value, 而 babel 或者其他编译器在通过 ts-api 编译文件时, 只能分析单个文件, 所以这些编译器导出的编译文件可能会在运行时出现问题

该选项设置为true时, ts 会在发现文件包含一些在单一文件编译过程中可能导致运行错误的代码时, 给出警告

比如:

typescript 复制代码
// foo.ts
export interface User {
  name: string;
}

// main.ts
import { User } from "./foo";

export { User }; // Error: Re-exporting a type when 'isolatedModules' is enabled requires using 'export type'.

// 正确的写法是
import { type User } from "./foo";

export { User };

// 或者
import { User } from "./foo";

export type { User };

开启这个选项的主要目的还是规范代码, 该有的标记一个都不能少, 该添加type修饰符的就加上去, 避免 babel 或其他编译器处理 ts 文件时产生无法预知的错误

用于控制在编译 TypeScript 代码时是否保留符号链接(symlinks)的原始结构。符号链接是一种文件系统中的特殊文件类型,它可以引用其他文件或目录。这个选项有两个可能的值:

true:表示保留符号链接的原始结构。当设置为 true 时,TypeScript 编译器会在编译过程中保持符号链接的原始路径和结构不变。

false(默认值):表示不保留符号链接的原始结构。当设置为 false 时,TypeScript 编译器会解析符号链接并使用它们的目标文件或目录进行编译。

如果项目中使用了符号链接,并且希望在编译过程中保留符号链接的原始结构以及相对路径信息,可以将 preserveSymlinks 设置为 true

如果项目中使用符号链接,但更关心符号链接的目标文件而不是原始结构,或者如果开发环境不依赖于符号链接的原始结构,那么使用默认值 false 可能更合适。

另一种情况是,如果在 Windows 操作系统上开发,由于 Windows 对符号链接的支持较有限,可能更倾向于使用 false,因为在 Windows 上编译时,true 可能会导致一些问题。

verbatimModuleSyntax

ts@5 版本引入的新选项, 用来简化importsNotUsedAsValues,preserveValueImports等两个选项

当设为true的时候, 任何importexport中没有type修饰符的代码都会被保留下来, 带有type修饰符的都会被完全删除

typescript 复制代码
// 编译前
import foo from "foo";

export const age = 1;

// 设置为false 编译后, // foo未被使用, 会被移除
export var age = 1;

// 设置为true 编译后
import foo from "foo";
export var age = 1;

再比如:

typescript 复制代码
// 编译前
import { type User } from "./foo"; // 这句也会被移除, 因为User只在ts中有效

export function init(user: User) {
  console.log("init");
}

// 设置为false 编译后
export function init(user) {
  console.log("init");
}

// 设置为true 编译后
import {} from "./foo";
export function init(user) {
  console.log("init");
}

需要注意的是, 如果项目编译目的设置为任何使用require或者module.exports的代码, verbatimModuleSyntax不要 设置为true, 否则 ts 会在编译过程中抛出错误

Backwards Compatibility 向后兼容相关选项

charset (deprecated)

在早期的 ts 版本中, 这个选项用来控制 ts 读取文件时所使用的编码, 现在默认值就是utf-8; 不需要另行配置

keyofStringsOnly (deprecated)

该选项已被弃用, 现在默认是 true 了

keyof是 ts 中的一个操作符: 假设有这么一段代码:

typescript 复制代码
export interface Person {
  name: string;
  age: number;
  address: string;
  [key: string]: unknown;
}

export type PersonKeys = keyof Person;

let t: PersonKeys = "name";
t = "age";
t = "address";
t = 2;

该选项设置为false时, 上面的代码是不会报错的, 因为export type PersonKeys = keyof Person;就相当于 type PersonKeys="name" | "age" | "address" | string | number

如果选项设置为true, t=2会抛出错误, 因为此时export type PersonKeys = keyof Person;就相当于 type PersonKeys="name" | "age" | "address"

noImplicitUseStrict (deprecated)

默认情况下, ts 在module选项设置为非 ES 时,会自动在输出文件头部添加use strict, 启用该选项会禁止这个行为

noStrictGenericChecks (deprecated)

假设有以下代码:

typescript 复制代码
type A = <T, U>(x: T, y: U) => [T, U];
type B = <S>(x: S, y: S) => [S, S];

function f(a: A, b: B) {
  b = a; // Ok
  a = b; // Error
}

默认情况下, ts 会提示如下错误信息, 因为把b赋值给a的时候, ts 会校验这两者的类型信息, 函数类型B的泛型参数明显少于A的参数, ts 默认是不允许此类行为的:

python 复制代码
Type 'B' is not assignable to type 'A'.
  Types of parameters 'y' and 'y' are incompatible.
    Type 'U' is not assignable to type 'T'.
      'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.

该选项设置为true, ts 将不再校验此类行为

out

该选项已弃用, 用outFile选项与outDir选项代替

suppressExcessPropertyErrors (deprecated)

该选项用来控制 ts 在检测到多余属性时是否报告异常

比如以下代码:

typescript 复制代码
const person: { name: string } = { name: "Alice", age: 30 };

这里面的age属性, 不在预定义的类型声明中, 默认情况下 ts 会报告异常

如果该选项设置为true, ts 不会报告此类异常

suppressImplicitAnyIndexErrors (deprecated)

该选项用来控制 ts 在检测到隐式 any时是否报告异常

比如以下代码:

typescript 复制代码
const obj = {
  name: "Alice",
  age: 30,
};

const prop = obj["address"]; // TypeScript 会发出类型错误

这里 ts 无法确定address的类型, 默认情况下 ts 会报告异常

如果该选项设置为true, ts 不会报告此类异常

该选项在新版本中可以使用noImplicitAny选项代替

extendedDiagnostics 编译分析相关选项

extendedDiagnostics

使用 extendedDiagnostics 编译选项,TypeScript 编译器会生成额外的详细诊断信息,更容易地定位和解决潜在的问题。

这个选项对于识别潜在问题、优化代码和进行代码审查非常有用。它提供了比默认诊断更多的信息,以便开发人员更好地理解其代码。

下面是该选项设为true后, 控制台的输出信息:

shell 复制代码
 ~/Documents/office/aprojects/zhongke/vary-ui/ts/ npx tsc

Files:                         156
Lines of Library:            38131
Lines of Definitions:        84722
Lines of TypeScript:             2
Lines of JavaScript:             0
Lines of JSON:                   0
Lines of Other:                  0
Identifiers:                126583
Symbols:                    241069
Types:                       67264
Instantiations:             170459
Memory used:               284856K
Assignability cache size:    22613
Identity cache size:           169
Subtype cache size:              0
Strict subtype cache size:       0
I/O Read time:               0.12s
Parse time:                  0.65s
ResolveTypeReference time:   0.01s
ResolveModule time:          0.02s
ResolveLibrary time:         0.03s
Program time:                0.88s
Bind time:                   0.26s
Check time:                  2.32s
transformTime time:          0.01s
commentTime time:            0.00s
I/O Write time:              0.01s
printTime time:              0.03s
Emit time:                   0.03s
Total time:                  3.49s

diagnostics

该选项是extendedDiagnostics选项的子集, 也会生成额外的详细诊断信息; 但它的输出信息少一些

下面是该选项设置为true时编译后的输出信息:

shell 复制代码
 ~/Documents/office/aprojects/zhongke/vary-ui/ts/ npx tsc

Files:              156
Lines:           122855
Identifiers:     126583
Symbols:         241069
Types:            67264
Instantiations:  170459
Memory used:    279910K
I/O read:         0.03s
I/O write:        0.00s
Parse time:       0.73s
Bind time:        0.23s
Check time:       1.95s
Emit time:        0.02s
Total time:       2.93s

traceResolution

这个选项设为true时, ts 会在编译过程中将输出有关模块解析的详细信息,包括 TypeScript 编译器在哪里找到了每个模块以及模块之间的依赖关系

explainFiles

这个选项设为true时, ts 会在编译过程中将输出有关模块解析和文件查找的详细信息,提供更为详细和全面的信息,适用于复杂的模块解析和依赖问题的诊断

generateCpuProfile

该选项只能通过 CLI 的方式使用

该选项用来告诉 ts 在编译完成后, 输出一份文件, 该文件内保存了本次编译过程中所有处理步骤在 cpu 中占用的时间, 主要目的是帮助开发人员分析构建速度缓慢的原因

shell 复制代码
# 使用方法
npm run tsc --generateCpuProfile tsc-output.cpuprofile

listFiles

该选项用来控制 ts 在构建过程中所有使用的.d.ts文件

如果 ts 抛出一些类似于未找到xxx的声明文件等错误, 或者想知道 ts 到底使用了哪些.d.ts文件时, 可以启用该选项

下面是输出案例:

shell 复制代码
 ~/Documents/office/aprojects/zhongke/vary-ui/ts/ npx tsc
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es5.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2016.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2017.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2018.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2019.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.dom.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.webworker.importscripts.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.scripthost.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.core.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.collection.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.generator.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.iterable.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.promise.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.proxy.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.reflect.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.symbol.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2016.array.include.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2017.date.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2017.object.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2017.string.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2017.intl.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2018.intl.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2018.promise.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2018.regexp.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2019.array.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2019.object.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2019.string.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2019.symbol.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2019.intl.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.bigint.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.date.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.promise.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.string.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.intl.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.es2020.number.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.esnext.intl.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.decorators.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/node_modules/typescript/lib/lib.decorators.legacy.d.ts
/Users/loki/Documents/office/aprojects/zhongke/vary-ui/ts/main.ts
...

listEmittedFiles

该选项用来控制 ts 在构建完成后输出所有的编译后文件列表

这个列表中包含了:

  • .js
  • .js.map
  • .d.ts
  • .d.ts.map

Output Formatting 输出相格式化关选项

noErrorTruncation

当错误信息过长, ts 会自动截取一部分错误消息

把该选项设为true, 会阻止 ts 的截取操作, 强制 ts 展示完整的错误信息(这个选项在 VSC 编辑器中也同样有效), 比如下面的案例:

typescript 复制代码
var x: {
  propertyWithAnExceedinglyLongName1: string;
  propertyWithAnExceedinglyLongName2: string;
  propertyWithAnExceedinglyLongName3: string;
  propertyWithAnExceedinglyLongName4: string;
  propertyWithAnExceedinglyLongName5: string;
  propertyWithAnExceedinglyLongName6: string;
  propertyWithAnExceedinglyLongName7: string;
  propertyWithAnExceedinglyLongName8: string;
};

// String representation of type of 'x' should be truncated in error message
var s: string = x;

默认提示:

shell 复制代码
 ~/Documents/office/aprojects/zhongke/vary-ui/ts/ npx tsc

main.ts:13:5 - error TS2322: Type '{ propertyWithAnExceedinglyLongName1: string; \
propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; \
propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; \
propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; \
propert...' is not assignable to type 'string'.

13 var s: string = x;
       ~


Found 1 error in main.ts:13

设置为true后:

shell 复制代码
 ~/Documents/office/aprojects/zhongke/vary-ui/ts/ npx tsc

main.ts:13:5 - error TS2322: Type '{ propertyWithAnExceedinglyLongName1: string; \
propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; \
propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; \
propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; \
propertyWithAnExceedinglyLongName8: string; }' is not assignable to type 'string'.

13 var s: string = x;
       ~


Found 1 error in main.ts:13

preserveWatchOutput

这个选项用于配置 TypeScript 编译器在监视模式下的行为。具体来说,preserveWatchOutput 有两个可能的值:

如果将 preserveWatchOutput 设置为 true(默认值),TypeScript 编译器会尽量保留输出文件,以便在发生错误时提供更多信息。这意味着即使有错误,也会生成输出文件,以便你可以查看部分编译结果,并更容易进行故障排除。这对于大型项目的快速迭代和调试非常有用。

如果将 preserveWatchOutput 设置为 false,TypeScript 编译器将在发现错误时删除输出文件,以确保输出始终保持与源代码同步。这对于在每次编译时都要求输出文件保持一致的情况很有用。

在大多数情况下,将 preserveWatchOutput 保持为默认值(true)是合适的,因为它有助于更好地理解错误并进行快速调试

pretty

该选项用于配置 ts 输出日志的时候使用带颜色文本, 默认值是true

Completeness 完整性配置选项

skipDefaultLibCheck

已弃用, 使用skipLibCheck选项代替

skipLibCheck

它用于控制 TypeScript 编译器是否要跳过对声明文件(.d.ts 文件)的类型检查。这个选项的默认值是 false

具体来说,skipLibCheck 有以下两个可能的值:

如果将 skipLibCheck 设置为 true,TypeScript 编译器将跳过对声明文件的类型检查。这意味着编译过程不会检查 .d.ts 文件中的类型错误。这在一些情况下可能会加快编译速度,尤其是在处理大型项目时。

如果将 skipLibCheck 设置为 false(默认值),TypeScript 编译器会执行对声明文件的类型检查,以确保它们的类型与实际代码的类型兼容。这对于类型安全和代码质量很重要,但可能会导致较长的编译时间。

在大多数情况下,将 skipLibCheck 保持为默认值(false)是合适的,因为它有助于确保你的代码与声明文件保持一致,从而减少潜在的类型错误。然而,在某些情况下,如果你确定你的声明文件是正确的,你可以将 skipLibCheck 设置为 true 以提高编译性能。

Watch Options 监视模式相关选项

该选项建议保持默认设置

ts 支持多种不同的方法跟踪文件与目录的变化, 不同的项目中, 每种方法的工作效率可能不一样, 所以 ts@3.8 版本开始引入了这个选项, 允许用户自行定义监视过程与方法

这写配置项一般写在watchOptions

javascript 复制代码
{
  "watchOptions":{
    // Use native file system events for files and directories
    "watchFile": "useFsEvents",
    "watchDirectory": "useFsEvents",
    // Poll files for updates more frequently
    // when they're updated a lot.
    "fallbackPolling": "dynamicPriority",
    // Don't coalesce watch notification
    "synchronousWatchDirectory": true,
    // Finally, two additional settings for reducing the amount of possible
    // files to track  work from these directories
    "excludeDirectories": ["**/node_modules", "_build"],
    "excludeFiles": ["build/fileWhichChangesOften.ts"]
  }
}

watchFile

有以下可用值:

fixedPollingInterval:以固定的时间间隔每秒多次检查每个文件是否有更改。

priorityPollingInterval:每秒多次检查每个文件是否有更改,但使用启发式方法检查某些类型的文件的频率低于其他文件的频率。

dynamicPriorityPolling:使用动态队列,其中不经常修改的文件将被较少检查。

useFsEvents(默认值):尝试使用操作系统/文件系统的本机事件进行文件更改。

useFsEventsOnParentDirectory:尝试使用操作系统/文件系统的本机事件来侦听文件父目录的更改

watchDirectory

在缺乏递归文件监视功能的系统下如何监视整个目录树的策略。

fixedPollingInterval:以固定的时间间隔每秒多次检查每个目录是否有更改。

dynamicPriorityPolling:使用动态队列,其中不经常修改的目录将被较少检查。

useFsEvents(默认值):尝试使用操作系统/文件系统的本机事件进行目录更改。

fallbackPolling

使用文件系统事件时,此选项指定当系统用完本机文件观察程序和/或不支持本机文件观察程序时使用的轮询策略。

fixedPollingInterval:以固定的时间间隔每秒多次检查每个文件是否有更改。

priorityPollingInterval:每秒多次检查每个文件是否有更改,但使用启发式方法检查某些类型的文件的频率低于其他文件的频率。

dynamicPriorityPolling:使用动态队列,其中不经常修改的文件将被较少检查。

synchronousWatchDirectory:禁用目录上的延迟监视。当可能同时发生大量文件更改时(例如,运行 npm install 时 node_modules 发生更改),延迟监视非常有用,但对于一些不太常见的设置,您可能希望使用此标志禁用它。

excludeFiles

停止 ts 监控某些指定文件的变动

javascript 复制代码
{
  "watchOptions": {
    "excludeFiles": ["temp/file.ts"]
  }
}

excludeDirectories

停止 ts 监控某些指定目录的变动

javascript 复制代码
{
  "watchOptions": {
    "excludeDirectories": ["**/node_modules", "_build", "temp/*"]
  }
}
相关推荐
小白学习日记1 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java2 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele2 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范
懒羊羊大王呀2 小时前
CSS——属性值计算
前端·css
DOKE2 小时前
VSCode终端:提升命令行使用体验
前端
xgq2 小时前
使用File System Access API 直接读写本地文件
前端·javascript·面试
用户3157476081352 小时前
前端之路-了解原型和原型链
前端
永远不打烊2 小时前
librtmp 原生API做直播推流
前端
北极小狐2 小时前
浏览器事件处理机制:从硬件中断到事件驱动
前端
无咎.lsy2 小时前
vue之vuex的使用及举例
前端·javascript·vue.js