# tsconfig.json

## 顶层配置

<table><thead><tr><th width="196.7734375">字段名</th><th>说明</th></tr></thead><tbody><tr><td><code>compilerOptions</code></td><td>用于设置 TypeScript 编译行为的选项集合。大多数配置都写在这里。</td></tr><tr><td><code>files</code></td><td>指定一组确切要编译的文件名（适合小项目）。</td></tr><tr><td><code>include</code></td><td>使用 glob 模式匹配要包含的文件（默认是 <code>**/*.ts</code> 等）。</td></tr><tr><td><code>exclude</code></td><td>排除不参与编译的文件或目录（默认是 <code>node_modules</code>）。</td></tr><tr><td><code>extends</code></td><td>继承另一个 <code>tsconfig</code> 文件，方便共享配置。</td></tr><tr><td><code>references</code></td><td>配置项目引用（Project References），用于大型项目拆分。</td></tr><tr><td><code>watchOptions</code></td><td>设置 <code>tsc --watch</code> 监听行为。</td></tr><tr><td><code>typeAcquisition</code></td><td>控制是否自动下载类型定义文件（一般用于 JS 项目）。</td></tr></tbody></table>

## 模块系统与路径解析

| 选项名                               | 默认值                                                   | 说明                                                             |
| --------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------- |
| `allowArbitraryExtensions`        | `false`                                               | 允许导入任意文件扩展名的模块（非标准扩展名），一般用于非 `.ts`、`.js` 文件的导入。                |
| `allowImportingTsExtensions`      | `false`                                               | 允许在导入路径中包含 `.ts` 等 TypeScript 文件扩展名。                           |
| `allowUmdGlobalAccess`            | `false`                                               | 允许访问 UMD 包中的全局变量（无需导入即可使用）。                                    |
| `baseUrl`                         | `undefined`                                           | 配置模块导入的基准目录，用于相对路径模块导入的基准。                                     |
| `customConditions`                | `undefined`                                           | 用于条件导入时自定义条件名称数组，影响包的条件导入分支解析。                                 |
| `module`                          | `esnext`                                              | 指定模块系统，如 `commonjs`、`amd`、`esnext`、`node16` 等，决定生成代码的模块格式。     |
| `moduleResolution`                | `node` (默认 module 不是 none) / `classic` (module: none) | 指定模块解析策略，`node` 模拟 Node.js 解析模块，`classic` 是老的 TypeScript 解析方式。 |
| `moduleSuffixes`                  | `undefined`                                           | 模块解析时，优先匹配指定后缀列表，用于支持多环境文件（比如 `.native.ts`、`.web.ts` 等）。       |
| `noResolve`                       | `false`                                               | 禁止模块解析，只进行语法检查，不生成输出文件。                                        |
| `paths`                           | `undefined`                                           | 路径映射，用于为模块导入配置别名映射规则。                                          |
| `resolveJsonModule`               | `false`                                               | 允许导入 `.json` 文件并将其视为模块。                                        |
| `resolvePackageJsonExports`       | `true`                                                | 启用对 `package.json` 中 `exports` 字段的解析。                          |
| `resolvePackageJsonImports`       | `true`                                                | 启用对 `package.json` 中 `imports` 字段的解析。                          |
| `rewriteRelativeImportExtensions` | `[".js", ".jsx", ".ts", ".tsx"]`                      | 允许重写相对导入扩展名，如 `.js` 导入重写为 `.ts`。                               |
| `rootDir`                         | `undefined`                                           | 输入文件的根目录，输出文件结构会相对于此目录进行保留。                                    |
| `rootDirs`                        | `undefined`                                           | 多个根目录，用于合并多个源文件目录为虚拟根目录，常用于项目多源目录。                             |
| `typeRoots`                       | `["node_modules/@types"]`                             | 指定包含类型声明包的目录列表。                                                |
| `types`                           | `undefined`                                           | 指定要包含的类型包名称列表，默认包含所有 `typeRoots` 下的类型包。                        |

### baseUrl

`baseUrl` 用于设置解析**裸模块导入路径**（bare specifiers）时的**基础目录**。简单来说，它允许你写出更短、更干净的 import 路径，而不用写相对路径如 `../../../`。

```js
project/
├── tsconfig.json
├── ex.ts
└── hello/
    └── world.ts
```

使用前：没有设置 `baseUrl`，只能使用相对路径：

```
// ex.ts
import { helloWorld } from "./hello/world";
```

使用后：设置 `"baseUrl": "./"`，可以这样写：

```
// ex.ts
import { helloWorld } from "hello/world"; // ✅ 更简洁
```

📌 特点

| 特性                  | 说明                                              |
| ------------------- | ----------------------------------------------- |
| 模块解析起点              | 从 `baseUrl` 所指定的目录开始查找模块。                       |
| 优先级高于 node\_modules | 如果模块名在 baseUrl 下找到了，就不会去 node\_modules 中找。      |
| 可与 `paths` 搭配使用     | 可搭配路径别名配置，提供更强的模块解析能力。                          |
| 不再强制与 `paths` 搭配    | 自 TypeScript 4.1 起，使用 `paths` 不再必须设置 `baseUrl`。 |

#### 注意事项

1. **只影响裸路径**：只影响像 `"hello/world"` 这种非相对路径的模块导入。
2. **不推荐单独使用**：文档中提到这个功能最初是为 AMD 浏览器加载器设计的，如果你使用 Node.js 或 Webpack，推荐配合 `paths` 使用。
3. **易与模块路径冲突**：若你导入的路径名与某个 npm 包名相同，可能出现歧义（会优先使用 baseUrl 路径）。

推荐搭配 paths 使用

```json
{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@utils/*": ["src/utils/*"],
      "@models/*": ["src/models/*"]
    }
  }
}
```

然后就能这样使用模块：

```import
import { User } from "@models/User";
```

| 是否应该使用 `baseUrl`？ | 建议                                             |
| ----------------- | ---------------------------------------------- |
| 在大型项目             | ✅ 建议配合 `paths` 使用                              |
| 纯 Node.js 项目      | ❌ 更建议使用 `module-alias` 或直接用 `paths` 替代 baseUrl |
| 多层级嵌套项目           | ✅ 有利于避免 `../../../` 导入                         |
| 仅为模块简化导入          | ✅ 建议使用，注意路径唯一性                                 |

### rootDir

`rootDir`用来指定 TypeScript 源文件的逻辑根目录，决定了输出目录中源代码的目录结构。

当你设置了 outDir 时，TypeScript 会在输出目录中保留从 rootDir 开始的目录结构。

默认情况下，TypeScript 会自动推断 `rootDir`，值为所有非申明文件的最长公共路径。

如果你启用了 `composite: true`，则默认值为 `tsconfig.json` 所在的目录。

```css
MyProj/
├── tsconfig.json
├── core/
│   ├── a.ts
│   ├── b.ts
│   └── sub/
│       └── c.ts
├── types.d.ts
```

默认推断 rootDir 为 core

```
MyProj/
└── dist/
    ├── a.js
    ├── b.js
    └── sub/
        └── c.js
```

如果你手动设置 `rootDir: "."`：

```json
{
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "."
  }
}
MyProj/
└── dist/
    └── core/
        ├── a.js
        ├── b.js
        └── sub/
            └── c.js
```

### typeRoots

`typeRoots` 用于指定 TypeScript 在编译时 **查找类型声明（`.d.ts`）文件的根目录**，默认情况下，所有可见的 `@types` 包都会被自动包含进编译中。

如果你没有设置 `typeRoots`：

* TypeScript 会自动查找所有位于 `node_modules/@types` 下的类型包；
* 查找会向上递归查找父级目录的 `node_modules/@types` 目录；

```js
project/
├── tsconfig.json
├── node_modules/
│   └── @types/
│       └── lodash/
└── src/
    └── index.ts
```

默认情况下，你可以直接使用 lodash 的类型定义（例如 `import _ from "lodash"`），无需额外配置。

当你设置了 `typeRoots` 选项后，**只有这些目录中的类型声明包才会被包含进来**，其他默认目录（如 `node_modules/@types`）将会被忽略。

```json
{
  "compilerOptions": {
    "typeRoots": ["./typings", "./vendor/types"]
  }
}
```

此时编译器只会从这两个路径中加载类型定义：

* `./typings`
* `./vendor/types`

不再包括 `./node_modules/@types`。

📌 使用建议

| 需求/场景                           | 建议                               |
| ------------------------------- | -------------------------------- |
| 使用社区提供的类型（如 @types）             | ✅ 不设置 `typeRoots`，使用默认行为更方便      |
| 使用项目私有的类型声明                     | ✅ 设置 `typeRoots`，配合放在指定文件夹里      |
| 想禁止从 `node_modules/@types` 自动加载 | ✅ 设置 `typeRoots` 且不包含该路径         |
| 要配合 `types` 字段指定具体包             | `typeRoots` 是指定根目录，`types` 是指定名称 |

### types

#### ✅ 作用：**精确指定需要包含的类型声明包（`@types/\*`）**

当你指定了 `types` 选项时，**只有你列出的 `@types` 包才会被包含**到全局类型作用域中。其他默认包含的类型将被忽略。

#### 🧱 默认行为（未设置 `types`）

如果你没有设置 `types`：

* TypeScript 默认会加载你项目路径下以及所有上层目录中的 `node_modules/@types/*` 下的类型包。
* 例如，会自动包含：

```
./node_modules/@types/node
../node_modules/@types/jest
../../node_modules/@types/express
```

设置 `types` 示例

```json
{
  "compilerOptions": {
    "types": ["node", "jest", "express"]
  }
}
```

在这个例子中，TypeScript 只会包含以下三个类型声明包：

```
./node_modules/@types/node
./node_modules/@types/jest
./node_modules/@types/express
```

**不会自动包含**其他 `@types/*` 类型（如 `@types/lodash` 等）。

🎯 `types` 的影响范围

| 功能               | 是否受影响  | 说明                                                             |
| ---------------- | ------ | -------------------------------------------------------------- |
| 全局类型注入           | ✅ 会被限制 | 例如 `process` (node)、`expect` (jest) 不再是全局变量                    |
| 自动导入推荐           | ✅ 会减少  | 编辑器不会推荐未包含的类型包中的导入                                             |
| `import` 导入的模块类型 | ❌ 不受影响 | `import moment from "moment"` 仍然会从 `@types/moment` 加载类型（如果已安装） |

#### ⚠️ 非常重要：`types` **不会限制通过 `import` 使用的类型**

即便你没在 `types` 中写 `moment`，下面代码依然有类型：

```
ts


复制编辑
import * as moment from "moment";
moment().format("YYYY-MM-DD");
```

这是因为 `import` 时 TypeScript 会根据导入语句去 `node_modules/moment` → `package.json` → `types` 字段 或 去 `@types/moment` 寻找声明。

#### `types` vs `typeRoots`

| 特性     | `types`                | `typeRoots`         |
| ------ | ---------------------- | ------------------- |
| 控制范围   | 精确列出哪些 `@types/*` 包会加载 | 指定哪些目录下的所有类型声明包会被加载 |
| 精度     | 更精细，只加载指定的包            | 更粗略，目录下的所有包都加载      |
| 覆盖默认行为 | 是                      | 是                   |
| 搭配场景   | 限制全局类型污染、加速编译          | 使用自定义类型声明存放路径       |

#### ✅ 使用建议

| 场景                                | 是否推荐使用 `types`  |
| --------------------------------- | --------------- |
| 你只需要用一小部分 `@types/*` 包（如仅 `node`） | ✅ 是             |
| 想避免 Jest、JSDOM、Cypress 的全局污染      | ✅ 是             |
| 不清楚项目使用了哪些类型包                     | ❌ 否（保持默认行为即可）   |
| 与 `typeRoots` 搭配使用私有类型            | ✅ 可混用，但要注意路径和命名 |

### moduleResolution

当你在代码中写 `import xxx from 'xxx'` 或 `require('xxx')` 时，TS 编译器需要知道：

* 去哪里找这个模块文件（比如是找 `node_modules` 里的包，还是本地文件）；
* 按照什么规则确定模块的最终路径（比如是否加 `.ts`/`.js` 后缀，是否识别 `package.json` 的 `exports` 字段等）。

`moduleResolution` 就是用来指定这套查找规则的，不同的规则适配不同的模块系统和运行环境。

**二、核心取值与场景选型（按推荐优先级排序）**

<table><thead><tr><th width="322.4609375">取值</th><th width="390.57421875">核心适配场景</th><th>关键特点</th></tr></thead><tbody><tr><td><code>bundler</code></td><td>前端项目（Webpack/Vite/Rollup 等打包工具）</td><td>1. 支持 <code>package.json</code> 的 <code>imports/exports</code>；2. 相对导入无需加文件后缀（符合前端习惯）</td></tr><tr><td><code>node16</code>/<code>nodenext</code></td><td>现代 Node.js 项目（v12+）</td><td>1. 严格遵循 Node.js v12+ 规范，区分 ESM/CJS；2. ESM 导入需加文件后缀；3. 与 <code>module: node16/nodenext</code> 配套使用</td></tr><tr><td><code>node10</code>（原 <code>node</code>）</td><td>旧版 Node.js 项目（v10 及以下）</td><td>1. 仅支持 CJS 解析规则；2. 无 ESM 相关逻辑</td></tr><tr><td><code>classic</code></td><td>极早期 TS 项目（v1.6 前）</td><td>已废弃，无 <code>node_modules</code> 解析逻辑，仅按简单路径查找</td></tr></tbody></table>

**三、实战配置示例**

## 类型检查

<table><thead><tr><th width="284.87109375">选项名</th><th width="109.3125">默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>allowUnreachableCode</code></td><td><code>false</code></td><td>允许代码中存在无法执行的代码（例如 <code>return</code> 后的语句）。</td></tr><tr><td><code>allowUnusedLabels</code></td><td><code>false</code></td><td>允许未使用的 label 语句（例如 <code>label: {}</code>）。</td></tr><tr><td><code>alwaysStrict</code></td><td><code>false</code></td><td>在编译输出的 JS 文件中自动添加 <code>"use strict"</code> 指令。</td></tr><tr><td><code>exactOptionalPropertyTypes</code></td><td><code>false</code></td><td>将可选属性视为 <code>{ foo?: T }</code> 与 <code>{ foo: Tundefined }</code> 不等价，更严格。</td></tr><tr><td><code>noFallthroughCasesInSwitch</code></td><td><code>false</code></td><td>阻止 <code>switch</code> 中 <code>case</code> 无 <code>break</code> 或 <code>return</code> 导致的意外贯穿。</td></tr><tr><td><code>noImplicitAny</code></td><td><code>false</code></td><td>不允许推断为 <code>any</code> 的隐式类型，必须显式声明。</td></tr><tr><td><code>noImplicitOverride</code></td><td><code>false</code></td><td>要求使用 <code>override</code> 关键字显式标注重写父类成员。</td></tr><tr><td><code>noImplicitReturns</code></td><td><code>false</code></td><td>所有代码路径必须显式 <code>return</code> 值（如果函数声明有返回类型）。</td></tr><tr><td><code>noImplicitThis</code></td><td><code>false</code></td><td>不允许 <code>this</code> 的隐式类型为 <code>any</code>，必须有明确上下文类型。</td></tr><tr><td><code>noPropertyAccessFromIndexSignature</code></td><td><code>false</code></td><td>禁止通过属性访问（点语法）访问仅定义了索引签名的属性。</td></tr><tr><td><code>noUncheckedIndexedAccess</code></td><td><code>false</code></td><td>启用对索引访问添加 <code>undefined</code> 类型，比如 <code>obj[key]</code> 推断为 <code>undefined</code></td></tr><tr><td><code>noUnusedLocals</code></td><td><code>false</code></td><td>报告未使用的局部变量。</td></tr><tr><td><code>noUnusedParameters</code></td><td><code>false</code></td><td>报告未使用的函数参数。</td></tr><tr><td><code>strict</code></td><td><code>false</code></td><td>一键开启所有严格类型检查选项（推荐：开启）。</td></tr><tr><td><code>strictBindCallApply</code></td><td><code>false</code></td><td>更严格检查 <code>bind</code>、<code>call</code>、<code>apply</code> 的参数类型匹配。</td></tr><tr><td><code>strictBuiltinIteratorReturn</code></td><td><code>false</code></td><td>要求标准迭代器返回 <code>{ value: T, done: boolean }</code> 的精确类型。</td></tr><tr><td><code>strictFunctionTypes</code></td><td><code>true</code>（启用 <code>strict</code> 时）</td><td>更严格的函数参数双向兼容性检查。</td></tr><tr><td><code>strictNullChecks</code></td><td><code>false</code></td><td>严格处理 <code>null</code> 和 <code>undefined</code>，不再隐式可赋值。</td></tr><tr><td><code>strictPropertyInitialization</code></td><td><code>false</code></td><td>要求类的每个属性都在构造函数中初始化，除非被标注为 <code>undefined</code> 或用 <code>!</code> 断言。</td></tr></tbody></table>

## 输出配置

<table><thead><tr><th width="363.76953125">选项名</th><th>默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>declaration</code></td><td><code>false</code></td><td>是否生成 <code>.d.ts</code> 类型声明文件。</td></tr><tr><td><code>declarationDir</code></td><td><code>undefined</code></td><td>指定生成声明文件的输出目录（如果设置了 <code>declaration</code>）。</td></tr><tr><td><code>declarationMap</code></td><td><code>false</code></td><td>是否为声明文件生成 <code>.map</code> 文件，方便调试声明文件。</td></tr><tr><td><code>downlevelIteration</code></td><td><code>false</code></td><td>启用对 ES6 迭代器语法的降级支持，兼容旧环境。</td></tr><tr><td><code>emitBOM</code></td><td><code>false</code></td><td>是否在输出文件开头添加 UTF-8 BOM 头。</td></tr><tr><td><code>emitDeclarationOnly</code></td><td><code>false</code></td><td>是否只生成声明文件，不生成 <code>.js</code> 文件。</td></tr><tr><td><code>importHelpers</code></td><td><code>false</code></td><td>使用 <code>tslib</code> 的辅助函数，减少输出文件体积。</td></tr><tr><td><code>inlineSourceMap</code></td><td><code>false</code></td><td>是否将 <code>.map</code> 文件内联到输出的 <code>.js</code> 文件中。</td></tr><tr><td><code>inlineSources</code></td><td><code>false</code></td><td>是否将源文件内容内联到 <code>.map</code> 文件中，便于调试器显示源代码。</td></tr><tr><td><code>mapRoot</code></td><td><code>undefined</code></td><td>用于修改生成 <code>.map</code> 文件中源码文件路径的根目录。</td></tr><tr><td><code>newLine</code></td><td><code>undefined</code></td><td>指定输出文件中换行符类型，<code>"crlf"</code> 或 <code>"lf"</code>。</td></tr><tr><td><code>noEmit</code></td><td><code>false</code></td><td>不生成输出文件，只进行类型检查。</td></tr><tr><td><code>noEmitHelpers</code></td><td><code>false</code></td><td>不生成辅助函数，通常与 <code>importHelpers</code> 配合使用。</td></tr><tr><td><code>noEmitOnError</code></td><td><code>false</code></td><td>如果存在错误，则不生成输出文件。</td></tr><tr><td><code>outDir</code></td><td><code>undefined</code></td><td>指定输出目录，所有生成的文件都会写入此目录。</td></tr><tr><td><code>outFile</code></td><td><code>undefined</code></td><td>将所有模块输出到一个文件，通常用于 <code>amd</code> 或 <code>system</code> 模块。</td></tr><tr><td><code>preserveConstEnums</code></td><td><code>false</code></td><td>保留 <code>const enum</code> 定义，不将其内联为常量。</td></tr><tr><td><code>removeComments</code></td><td><code>false</code></td><td>是否从输出文件中移除注释。</td></tr><tr><td><code>sourceMap</code></td><td><code>false</code></td><td>是否生成 <code>.map</code> 文件，方便调试。</td></tr><tr><td><code>sourceRoot</code></td><td><code>undefined</code></td><td>指定源码根路径，用于 <code>.map</code> 文件中。</td></tr><tr><td><code>stripInternal</code></td><td><code>false</code></td><td><p></p><p>是否从声明文件中去除带有 <code>@internal</code> 注释的声明。</p></td></tr></tbody></table>

## JavaScript 支持

| 选项名                    | 默认值     | 说明                                                                              |
| ---------------------- | ------- | ------------------------------------------------------------------------------- |
| `allowJs`              | `false` | 允许编译器处理 `.js` 和 `.jsx` 文件。开启后可以将 JavaScript 文件包含进编译过程。                          |
| `checkJs`              | `false` | 对 `.js` 文件启用类型检查。需要 `allowJs` 为 `true` 才有效。                                     |
| `maxNodeModuleJsDepth` | `0`     | 限制从 `node_modules` 目录中递归编译 `.js` 文件的深度。默认值 `0` 表示不编译任何 `node_modules` 里的 JS 文件。 |

## 编辑器支持

## 模块互操作

<table><thead><tr><th width="340.5234375">选项名</th><th width="231.33203125">默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>allowSyntheticDefaultImports</code></td><td><code>true</code>（如果模块支持）</td><td>允许从没有默认导出的模块默认导入，比如 <code>import foo from "foo"</code>，用于兼容 CommonJS。</td></tr><tr><td><code>erasableSyntaxOnly</code></td><td><code>false</code></td><td>（较少使用）使语法节点可以被擦除，主要用于增量编译的内部处理。</td></tr><tr><td><code>esModuleInterop</code></td><td><code>false</code></td><td>启用对 CommonJS 模块默认导入的兼容处理，使得 <code>import x from "mod"</code> 正确工作。</td></tr><tr><td><code>forceConsistentCasingInFileNames</code></td><td><code>false</code></td><td>强制在模块导入路径中大小写必须一致，防止跨平台大小写敏感问题。</td></tr><tr><td><code>isolatedDeclarations</code></td><td><code>false</code></td><td>启用声明文件的隔离生成，保证每个文件的声明是独立的，常用于大型项目和声明文件库。</td></tr><tr><td><code>isolatedModules</code></td><td><code>false</code></td><td>启用单文件编译模式，适合 Babel 等工具链，禁止使用跨文件类型检查的功能。</td></tr><tr><td><code>preserveSymlinks</code></td><td><code>false</code></td><td>模块解析时是否保留符号链接，默认会解析符号链接为真实路径。</td></tr></tbody></table>

### erasableSyntaxOnly

可擦出语法就是可以直接去掉的，仅在编译时存在，不会生成额外运行时代码的语法，例如`type`、`interface`。不可擦出语法就是不能直接去掉的，需要编译为JS且会生成额外运行时代码的语法，例如 `enum`，`namespace`。

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>不可擦出语法，生成额外的运行代码</td><td data-object-fit="contain"><a href="https://1513904068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYmNQQ0tmQhGBUSZWnpYS%2Fuploads%2FKqOGT4KRPBYSlz1s4DDE%2Fimage.png?alt=media&#x26;token=ad14f2a1-0fd4-48f4-86e7-a7e1ad568927">image.png</a></td></tr><tr><td>可擦出语法，不会生成额外的运行代码</td><td data-object-fit="contain"><a href="https://1513904068-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYmNQQ0tmQhGBUSZWnpYS%2Fuploads%2FH8MGoYWbcsJxocpBLeIG%2Fimage.png?alt=media&#x26;token=a67ec435-2ec0-4c78-b5c7-85f1b29abbb3">image.png</a></td></tr></tbody></table>

Enum 的替代方案

#### const enum

```typescript
const enum Method {
  GET = "GET",
  POST = "POST",
  PUT = "PUT",
  PATCH = "PATCH",
};

function getMethod(method: Method) {
  return method;
}

getMethod(Method.GET)
getMethod("GET") // 报错
```

#### 联合类型

```typescript
type Method = "GET" | "POST" | "PUT" | "PATCH";

function getMethod(method: Method) {
  return method;
}

getMethod("GET")
getMethod("post") // 报错
```

#### 类型字面量 + as const

```
const Method = {
  GET: "GET",
  POST: "POST",
  PUT: "PUT",
  PATCH: "PATCH",
};
type MethodType = typeof Method[keyof typeof Method];

function getMethod(method: MethodType) {
  return method;
}

getMethod(Method.GET)
getMethod("GET")
```

### esModuleInterop

`esModuleInterop` 本质是抹平 CommonJS 和 ES Module 之间的交互差异，主要做两件事：

1. 启用`allowSyntheticDefaultImports`（合成默认导入）
   1. 自动为没有 `default` 导出的 CJS 模块生成一个 “合成的 default 导出”。
   2. 允许你用 `import React from 'react'` 替代 `import * as React from 'react'`，符合 ESM 的书写习惯，且不会报错。
2. 注入辅助函数（\_\_importDefault /\_\_importStar）
   1. TS 会在编译后的代码中注入两个辅助函数，处理模块导入的适配：
   2. `__importDefault`：将 CJS 模块的 `module.exports` 作为 ESM 的 `default` 导出。
   3. `__importStar`：将 CJS 模块转换为符合 ESM 规范的命名空间对象。

{% tabs %}
{% tab title="关闭 esModuleInterop （默认为 false）" %}

```typescript
// 代码书写（会报错）
import fs from 'fs'; // 报错：Module '"fs"' has no default export.

// 必须这样写（不符合习惯）
import * as fs from 'fs';
```

{% endtab %}

{% tab title="开启 esModuleInterop" %}

```typescript
// tsconfig.json
{
  "compilerOptions": {
    "esModuleInterop": true,
    "module": "commonjs", // 通常配合 commonjs 使用
    "target": "es6"
  }
}

// 代码书写（正常）
import fs from 'fs'; // 无报错，符合 ESM 习惯
import React from 'react'; // 同理，React 是 CJS 模块也能这样导入

// 编译后的 JS（自动注入辅助函数）
var __importDefault = (this && this.__importDefault) || function (mod) {
  return (mod && mod.__esModule) ? mod : { "default": mod };
};
const fs = __importDefault(require('fs')).default;

```

{% endtab %}
{% endtabs %}

## 兼容性设置

<table><thead><tr><th width="361.82421875">选项名</th><th width="243.7109375">默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>charset</code></td><td><code>undefined</code></td><td>指定输出文件的字符集，通常不用设置，默认 UTF-8。</td></tr><tr><td><code>importsNotUsedAsValues</code></td><td><code>"remove"</code></td><td>控制未作为值使用的导入行为：<code>"remove"</code> 删除，<code>"preserve"</code> 保留，<code>"error"</code> 报错。</td></tr><tr><td><code>keyofStringsOnly</code></td><td><code>false</code></td><td>限制 <code>keyof</code> 操作符结果只能是字符串类型（兼容旧版行为）。</td></tr><tr><td><code>noImplicitUseStrict</code></td><td><code>false</code></td><td>禁止编译器自动在输出文件中插入 <code>"use strict"</code>。</td></tr><tr><td><code>noStrictGenericChecks</code></td><td><code>false</code></td><td>放宽对泛型函数调用的严格类型检查。</td></tr><tr><td><code>out</code></td><td><code>undefined</code></td><td>将所有模块编译成一个输出文件，已被 <code>outFile</code> 取代，不建议使用。</td></tr><tr><td><code>preserveValueImports</code></td><td><code>false</code></td><td>保留所有的导入语句，即使它们未被用作值，避免导入被错误移除。</td></tr><tr><td><code>suppressExcessPropertyErrors</code></td><td><code>false</code></td><td>抑制多余属性检查导致的错误，允许对象多余属性存在。</td></tr><tr><td><code>suppressImplicitAnyIndexErrors</code></td><td><code>false</code></td><td>抑制对隐式 <code>any</code> 索引签名的错误。</td></tr></tbody></table>

## 语言与环境

<table><thead><tr><th width="328.16796875">选项名</th><th width="275.17578125">默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>emitDecoratorMetadata</code></td><td><code>false</code></td><td>启用时会为装饰器生成设计类型元数据，方便依赖注入等反射机制。</td></tr><tr><td><code>experimentalDecorators</code></td><td><code>false</code></td><td>启用实验性的装饰器语法支持。</td></tr><tr><td><code>jsx</code></td><td><code>"preserve"</code></td><td>指定 JSX 代码的处理方式，可选 <code>"preserve"</code>, <code>"react"</code>, <code>"react-native"</code>, <code>"react-jsx"</code>, <code>"react-jsxdev"</code> 等。</td></tr><tr><td><code>jsxFactory</code></td><td><code>"React.createElement"</code></td><td>指定 JSX 的工厂函数名，比如用其它库替代 React。</td></tr><tr><td><code>jsxFragmentFactory</code></td><td><code>"React.Fragment"</code></td><td>指定 JSX Fragment 的工厂函数名。</td></tr><tr><td><code>jsxImportSource</code></td><td><code>undefined</code></td><td>指定用于 JSX 转换的导入源（用于自动导入 JSX 运行时，例如 <code>@emotion/react</code>）。</td></tr><tr><td><code>lib</code></td><td><code>["dom", "esnext"]</code></td><td>指定要包含的库文件（比如 <code>es2015</code>, <code>dom</code> 等），影响全局类型。</td></tr><tr><td><code>libReplacement</code></td><td><code>undefined</code></td><td>用于替代某些默认库的替换方案（一般不用修改）。</td></tr><tr><td><code>moduleDetection</code></td><td><code>"auto"</code></td><td>模块检测策略，自动检测文件是否为模块。</td></tr><tr><td><code>noLib</code></td><td><code>false</code></td><td>不包含默认的库文件，通常不建议开启。</td></tr><tr><td><code>reactNamespace</code></td><td><code>"React"</code></td><td>指定 React 命名空间（通常默认 React）。</td></tr><tr><td><code>target</code></td><td><code>"esnext"</code></td><td>编译输出的 JavaScript 版本目标，如 <code>es5</code>, <code>es6</code>, <code>es2017</code> 等。</td></tr><tr><td><code>useDefineForClassFields</code></td><td><code>false</code></td><td>是否使用 ES 标准的 <code>define</code> 来初始化类字段，影响类字段的初始化行为和兼容性。</td></tr></tbody></table>

### jsx

* `react-jsx`：编译为`_jsx`调用（自动引入 React，优化生产环境），基于 React 17+ 新 JSX 转换。
* `react-jsxdev`：编译为`_jsxDEV`调用，保留调试信息，适用于开发环境，提供更好的错误提示和 DevTools 支持。
* `react`：编译为`React.createElement()`，旧版 React JSX 转换方式，需要显示导入 React。
* `preserve`：保留`.tsx`文件中的 JSX 原样，输出`.jsx`文件(不转译)
* `react-native`：也保留 JSX，但输出 `.js` 文件，专用于 React Native 项目。

```tsx
const App = () => <div>Hello</div>;
```

```js
// react-jsx（或 react-jsxdev）：
import { jsx as _jsx } from "react/jsx-runtime";
const App = () => _jsx("div", { children: "Hello" });

// react
import React from "react";
const App = () => React.createElement("div", null, "Hello");

// preserve
const App = () => <div>Hello</div>;

// react-native
const App = () => <div>Hello</div>;
```

### Target

`target`设置决定 TypeScript 编译输出的 JavaScript 语言版本。

常见取值

| `target` 值         | 描述                          | 适用平台或版本            |
| ------------------ | --------------------------- | ------------------ |
| `ES3`              | 最旧支持（已极少使用）                 | 旧版 IE6\~IE8（已废弃）   |
| `ES5`              | 较旧支持，含 polyfill 机会大         | IE11、老 Android 浏览器 |
| `ES6` / `ES2015`   | 增加类、模块、箭头函数等语法              | 现代浏览器普遍支持（推荐最低选项）  |
| `ES2016`\~`ES2022` | 每年一版，逐步加入新特性（如 `**`, async） | Node.js 12+、现代浏览器  |
| `ESNext`           | 使用当前 TypeScript 支持的最新语法     | 尽量避免用于库发布，版本依赖不稳定  |

✅ 示例：项目推荐设置

<table><thead><tr><th width="317.5703125">选项名</th><th width="199.2421875">默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>composite</code></td><td><code>false</code></td><td>开启增量编译项目支持，要求 <code>declaration</code> 和 <code>outDir</code>，用于构建大型项目和项目引用（Project References）。</td></tr><tr><td><code>disableReferencedProjectLoad</code></td><td><code>false</code></td><td>禁止自动加载引用的项目配置文件，通常用于提升大型项目构建性能。</td></tr><tr><td><code>incremental</code></td><td><code>false</code></td><td>启用增量编译，TypeScript 会保存 <code>.tsbuildinfo</code> 文件，下一次编译时复用先前状态加快编译速度。</td></tr><tr><td><code>tsBuildInfoFile</code></td><td><code>undefined</code></td><td>指定 <code>.tsbuildinfo</code> 文件的输出路径，默认为 <code>outDir</code> 目录下的 <code>tsconfig.tsbuildinfo</code>。</td></tr></tbody></table>

```json
{
  "compilerOptions": {
    "target": "ES2020", // 输出符合 ES2020 的 JS
    "lib": ["DOM", "ES2020"], // 可选：覆盖默认 lib
    "module": "ESNext",
    "strict": true,
    "esModuleInterop": true
  }
}
```

## 完整性检查

<table><thead><tr><th width="343.34765625">选项名</th><th width="159.796875">默认值</th><th>说明</th></tr></thead><tbody><tr><td><code>skipDefaultLibCheck</code></td><td><code>false</code></td><td>是否跳过对默认库文件（如 <code>lib.d.ts</code>）的类型检查，提升编译性能。</td></tr><tr><td><code>skipLibCheck</code></td><td><code>false</code></td><td>是否跳过对所有声明文件（<code>.d.ts</code> 文件）的类型检查，能显著减少大型项目的编译时间。</td></tr></tbody></table>

## 多项目与工程构建配置

<table><thead><tr><th width="376.31640625">配置项</th><th width="325.39453125">默认值</th><th>说明</th><th>作用与使用场景</th></tr></thead><tbody><tr><td><code>composite</code></td><td><code>false</code></td><td>启用该选项表示该项目是一个可编译为独立单元的 TypeScript 项目（即“增量项目”）。必须启用才能作为 <code>projectReferences</code> 的引用目标。</td><td>会强制生成 <code>.tsbuildinfo</code> 文件。要求每个文件必须有 <code>export</code> 或 <code>import</code>。</td></tr><tr><td><code>disableReferencedProjectLoad</code></td><td><code>false</code></td><td>在构建包含 <code>projectReferences</code> 的项目时，禁止加载引用的项目。</td><td>加快启动速度，仅适合工具/IDE，不适用于 <code>tsc --build</code>。</td></tr><tr><td><code>disableSolutionSearching</code></td><td><code>false</code></td><td>禁止搜索包含该文件的 solution（顶层 tsconfig）项目。</td><td>在大型项目中精确指定 <code>tsconfig</code> 作用范围时使用。</td></tr><tr><td><code>disableSourceOfProjectReferenceRedirect</code></td><td><code>false</code></td><td>禁止从引用项目中重定向源文件（默认会引用源代码而不是编译结果）。</td><td>启用后将强制使用 <code>.d.ts</code> 等编译结果，不再跟踪源文件变动，提升构建稳定性。</td></tr><tr><td><code>incremental</code></td><td><code>false</code></td><td>启用增量构建，会记录构建信息以加快后续构建速度。默认不会启用。</td><td>启用后，会自动生成 <code>tsBuildInfoFile</code> 指定的文件。</td></tr><tr><td><code>tsBuildInfoFile</code></td><td><code>.tsbuildinfo</code>（在 <code>outDir</code> 内部）</td><td>指定存储增量构建信息的文件路径。</td><td>通常不需要手动设置，仅在构建系统定制化时使用（如 Git 分离输出）。</td></tr></tbody></table>
