TSConfig备忘录

tsconfig.json是一个巨大的文件,包含大量潜在选项,能够吓到了每个人。

但实际上,你只需要关心几个配置选项。让我们找出它们,并制作速查表。

快速开始

只想要代码?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"compilerOptions": {
/* 基本选项: */
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
/* 严格性 */
"strict": true,
"noUncheckedIndexedAccess": true,
/* 如果使用 TypeScript 进行转译: */
"moduleResolution": "NodeNext",
"module": "NodeNext",
"outDir": "dist",
"sourceMap": true,
/* 还有如果你正在构建一个库: */
"declaration": true,
/* 以及如果你在单体库中构建一个库: */
"composite": true,
"declarationMap": true,
/* 如果不使用 TypeScript 进行转译: */
"moduleResolution": "Bundler",
"module": "preserve",
"noEmit": true,
/* 如果你的代码在 DOM 中运行: */
"lib": ["es2022", "dom", "dom.iterable"],
/* 如果你的代码不在 DOM 中运行: */
"lib": ["es2022"]
}
}

全面解释

基本选项

以下是我建议所有项目使用的基本选项。

1
2
3
4
5
6
7
8
9
10
11
{
"compilerOptions": {
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true
}
}
  • esModuleInterop:帮助修复 CommonJSES 模块之间的一些障碍。
  • skipLibCheck:跳过检查.d.ts文件的类型。这对性能很重要,否则所有的 node_modules 都会被检查。
  • target:你要目标的 JavaScript 版本。我推荐 es2022 而不是 esnext,因为它更稳定。
  • allowJs 和 resolveJsonModule:允许你导入.js.json文件。非常有用。
  • moduleDetection:此选项强制 TypeScript 将所有文件视为模块。这有助于避免“无法重新声明块作用域变量”错误。
  • isolatedModules:此选项防止了一些在将模块视为隔离文件时不安全的 TS 特性。
    严格性
    以下是我建议所有项目使用的严格性选项。
1
2
3
4
5
6
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true
}
}
  • strict: 启用所有严格的类型检查选项。不可或缺。
  • noUncheckedIndexedAccess: 在访问数组或对象之前,防止未先检查其是否已定义。这是防止运行时错误的好方法,应该真正包含在严格模式中。
    许多人推荐在 tsconfig/bases 中使用严格性选项,这是一个很棒的仓库,记录了 TSConfig 的选项。这些选项包括许多我认为太“复杂”的规则,如 noImplicitReturnsnoUnusedLocalsnoUnusedParametersnoFallthroughCasesInSwitch。我建议你只有在需要时才将这些规则添加到你的 tsconfig.json 中。
使用 TypeScript 进行转译

如果你正在使用 tsc 进行代码转译(创建 JavaScript 文件),你会想要这些选项。

1
2
3
4
5
6
7
{
"compilerOptions": {
"moduleResolution": "NodeNext",
"module": "NodeNext",
"outDir": "dist"
}
}
  • moduleResolution: 告诉 TypeScript 如何解析模块。对于你编写的代码是要在 Node 中运行的情况,NodeNext 是最佳选项。
  • module: 告诉 TypeScript 使用什么模块语法。对于 NodeNodeNext 是最佳选项。
  • outDir: 告诉 TypeScript 将编译后的 JavaScript 文件放在哪里。dist 是默认的约定,但可以你自定义。

构建库

如果你正在构建一个库,你会想要 declaration: true

1
2
3
4
5
{
"compilerOptions": {
"declaration": true
}
}
  • declaration: 告诉 TypeScript 生成.d.ts文件。这是必需的,这样库可以在你创建的 .js 文件上获得自动补全。
在单体库中构建库

如果你在单体库中构建一个库,你还会想要这些选项。

1
2
3
4
5
6
7
8
{
"compilerOptions": {
"declaration": true,
"composite": true,
"sourceMap": true,
"declarationMap": true
}
}
  • composite: 告诉 TypeScript 生成.tsbuildinfo文件。这告诉 TypeScript 你的项目是单体库的一部分,并帮助它缓存构建以提高运行速度。
  • sourceMap 和 declarationMap: 告诉TypeScript生成源映射和声明映射。这些是必需的,这样你的库的使用者在调试时可以跳转到原始源代码。
    不使用 TypeScript 进行代码转译
    如果你不使用 tsc 进行代码转译,也就是说,将 TypeScript 更多地用作 linter,你会想要这些选项。
1
2
3
4
5
6
7
{
"compilerOptions": {
"moduleResolution": "Bundler",
"module": "preserve",
"noEmit": true
}
}
  • moduleResolution: 对于你编写的代码需要与类似 WebpackRollupBabelSWCESBuild 等工具一起打包的情况,Bundler 是最佳选项。
  • module: preserve 是最佳选项,因为它最接近Bundler处理模块的方式。
在 DOM 中运行

如果你的代码在 DOM 中运行,你会想要这些选项。

1
2
3
4
5
{
"compilerOptions": {
"lib": ["es2022", "dom", "dom.iterable"]
}
}
  • lib: 告诉 TypeScript 包含哪些内置类型。对于稳定性,es2022 是最佳选项。dom dom.iterable 为你提供了 windowdocument 等类型。
不在 DOM 中运行

如果你的代码不在 DOM 中运行,你会想要 lib: ["es2022"]

1
2
3
4
5
{
"compilerOptions": {
"lib": ["es2022"]
}
}

这与上述相同,但没有domdom.iterable 类型。