越来越多的项目用上了 TypeScript,因此如何按需配置 tsconfig 也应该是前端工程师需要掌握的技能之一。

tsconfig.json 文件

tsconfig.json 文件是用于描述将 TypeScript 转为 JavaScript 代码的配置文件。

IDE(代码编辑器)将会根据 tsconfig.json 文件来对当前项目中支持不同程度的类型约束,同时也是对 TSC 编译 TypeScript 代码过程做一些预定义、约束入口和编译输出目录等配置。

因此对于一个支持 TypeScript 编程语言的工程来说,tsconfig.json 文件就是编码的基础。

二、tsconfig.json 配置详解 ⚙️

有了上面的前置知识作为基石,相信大家会对 tsconfig.json 文件的配置项也会更加容易理解。

tsconfig.json 编译配置 - 图1

2.1 files 指定需要编译的文件

files 字段用于指明需要 tsc 编译的一个或多个 ts 文件,例如:

{"files": ["index.ts", "global.d.ts"], }

当指定的文件或文件夹不存在时,会提示 ❌ 错误!

2.2 include 指定需要编译的文件范围

include 字段用于指明需要被 tsc 编译的文件或文件夹列表,例如:

默认是对 src 下的.ts、.d.ts、.tsx、.vue结尾的文件都需要进行编译

  1. "include": [
  2. "src/**/*.ts",
  3. "src/**/*.d.ts",
  4. "src/**/*.tsx",
  5. "src/**/*.vue",
  6. "tests/**/*.ts",
  7. "tests/**/*.tsx"
  8. ],

2.3 exclude 配置不需要编译的文件范围

exclude 字段用于排除不需要 tsc 编译的文件或文件夹列表,例如:

  1. {
  2. "exclude":[
  3. "test.ts",
  4. "src/test.ts",
  5. "node_modules",
  6. "dist"
  7. ],
  8. }

注意: exclude 字段中的声明只对 include 字段有排除效果,对 files 字段无影响,即与 include 字段中的值互斥。

如果 tsconfig.json 文件中 filesinclude 字段都不存在,则默认包含 tsconfig.json 文件所在目录及子目录的所有文件,且排除在 exclude 字段中声明的文件或文件夹。

references 将 TypeScript 程序拆分

属性是 TypeScript 3.0 的新特性,允许将 TypeScript 程序拆分结构化。这和我们写 vue 组件的思想有着异曲同工之妙,避免了在一个文件中处理过多的内容,而是通过拆分成多个文件,分别配置不同的部分,达到更加清晰,可维护性更高的目的。

  1. {
  2. "compilerOptions": {
  3. "target": "esnext",
  4. "useDefineForClassFields": true,
  5. "module": "esnext",
  6. "moduleResolution": "node",
  7. "strict": true,
  8. "jsx": "preserve",
  9. "sourceMap": true,
  10. "resolveJsonModule": true,
  11. "esModuleInterop": true,
  12. "lib": ["esnext", "dom"]
  13. },
  14. "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  15. "references": [{ "path": "./tsconfig.node.json" }]
  16. }

🙌🌰初始化 vite 项目的配置,项目根目录下生成了 tsconfig.jsontsconfig.node.json 两个文件,tsconfig.json 指定了用来编译这个项目的根文件和编译选项;而tsconfig.node.json中的"include": ["vite.config.ts"]表明这个单独拆分出来的配置文件只是负责编译 vite 的配置文件vite.config.ts

  1. {
  2. "compilerOptions": {
  3. "composite": true,
  4. "module": "esnext",
  5. "moduleResolution": "node"
  6. },
  7. "include": ["vite.config.ts"]
  8. }

2.4 compileOnSave 保存时编译

compileOnSave 是声明是否需要在保存时候自动触发 tsc 编译的字段,一般来说,我们的代码编译过程会通过 Rollup、Webpack 等打包构建工具,并且使用热更新,因此无需配置该项,保持缺省即可。

{"compileOnSave": false,}

2.5 extends 继承已有配置文件

extends 字段用于指明继承已有的 tsconfig 配置规则文件。

该字段可以说是非常有用了,因为我们的 tsconfig 配置其实各个项目之间大同小异,因此完全可以结合自己团队的情况,抽离一个基础且公共的 tsconfig 配置,并将其发包,然后作为 extends 字段的值来继承配置。

tsconfig 推荐默认配置可以参考官方的包:@tsconfig/recommended

@tsconfig/recommended 的配置如下:

  1. {
  2. "compilerOptions": {
  3. "target": "ES2015",
  4. "module": "commonjs",
  5. "strict": true,
  6. "esModuleInterop": true,
  7. "skipLibCheck": true,
  8. "forceConsistentCasingInFileNames": true
  9. },
  10. "$schema": "https://json.schemastore.org/tsconfig",
  11. "display": "Recommended"
  12. }

例如继承一个发包后的 tsconfig 基础配置,并通过显示声明编译的目标代码版本为 ES2016 来覆盖覆盖 @tsconfig/recommended 中对应配置项。

  1. {
  2. "extends": "@tsconfig/recommended/tsconfig.json",
  3. "compilerOptions": {
  4. "target": "ES2016"
  5. }
  6. }

作为一些实践经验,社区也提供了一些常见环境(例如:Nuxt、Vite、Node 等)最佳实践后的基础配置

2.6 compilerOptions 编译选项

compilerOptions 是一个描述 TypeScript 编译器功能的 “大” 字段,其值类型是“对象”,因此包含了很多用于描述编译器功能的子字段,其子字段的功能如下:

target

target 字段指明经过 TSC 编译后的 ECMAScript 代码语法版本,根据 ECMAScript 语法标准,默认值为 ES3

TypeScript 是 JavaScript 的超集,是对 JavaScript 语法和类型上的扩展,因此我们可以使用 ES5、ES6,甚至是最新的 ESNext[4] 语法来编写 TS。例如当我们使用 ES2021 语法来编码 TS 文件,同时配置如下:

{ "compilerOptions": {"target": "ES5",} }

则会将对应使用了最新 ECMAScript 语法的 TS 文件编译为符合 ES5 语法规范的 *.js 文件。

延伸一下知识点,思考一下 tsc 是如何将高版本(ECMAScript 规范)代码向低版本代码转换的?这个转换的结果靠谱吗?与 Babel 有何差异?

tsconfig.json 编译配置 - 图2

一图看 ECMAScript 各版本功能差异

另外对于个版本差异有想简单了解的👬,可以阅读《1.5 万字概括 ES6 全部特性[5]》

通过一个实验,在 src/index.ts 文件中使用了 Map、Async/Await、Promise、扩展运算符,并在 tsconfig.jon -> target 设置为 ES5

tsconfig.json 编译配置 - 图3

验证 target 降级处理

然后发现在右侧的 dist/index.js 文件中,依然存在 new Map() 、Promise 语法,因此可以得出结论:tsc 的代码降级编译并不能完全处理兼容性

通过官方文档了解到:

tsconfig.json 编译配置 - 图4

这里提到了 lib 字段,意思是 target 不同的值会有对应默认的 lib 字段值,当然也支持开发者显示指明 lib 字段的值,那么接下来看看 lib 是干嘛的吧!

lib 指明ECMAScript 语法或环境对应的类型声明文件

lib 字段是用于为了在我们的代码中显示的指明需要支持的 ECMAScript 语法或环境对应的类型声明文件。

例如我们的代码会使用到浏览器中的一些对象 windowdocument,这些全局对象 API 对于 TypeScript Complier 来说是不能识别的:

tsconfig.json 编译配置 - 图5

lib 未显示引入 DOM 会提示类型错误

因而需要在 lib 字段中如下配置:

  1. {
  2. "compilerOptions": {
  3. "target": "esnext",
  4. "lib": ["esnext", "dom", "dom.iterable","scripthost"],
  5. }
  6. }

来显式引入在 DOM 即浏览器环境下的一些默认类型定义,即可在代码中使用,windowdocument 等浏览器环境中的对象,TS 在运行时以及编译时就不会报类型错误。

tsconfig.json 编译配置 - 图6

引入类型定义后无错误提示

如果你的项目涉及到WebWorker API,需要添加到 lib 字段中

  1. "lib": ["ESNext", "DOM", "WebWorker"],

综合 targetlib 字段的实际功能表现,我们可以得出结论

TSC 的编译结果只有部分特性做了 pollyfill 处理,ES6 的一些特性仍然被保留,想要支持完全的降级到 ES5 还是需要额外引入 pollyfill(也就是我们在项目的入口文件处 import 'core-js'),但建议是将 target 字段值设置为 ES6,提升 TSC 的速度。

因此,笔者对于使用 TSC 编译的观点是:

不应该将 **TSC** 作为编译项目的工具,应该将 **TSC** 作为类型检查工具,代码编译的工作尽量交给 **Rollup****Webpack****Babel** 等打包工具!

(3). module

module 字段指明 tsc 编译后的代码应该符合何种 “模块化方案”,可以指定的枚举值有:none, commonjs, amd, system, umd, es2015, es2020, 或 ESNext,默认值为 none

在如今的前端开发趋势来讲,主要是使用 ESM、CommonJS、UMD、IIFE 四种模块化方案,未来会趋向于 ESM,当然我们会根据项目的应用场景来决定使用何种模块化方案,例如:NodeJS 使用 CommonJS,浏览器里可以使用 ESM,不过现在的打包工具,会自动处理 CommonJS 和 ESM 的差异,并包装成符合指定模块化规范的代码,

在 tsconfig.json 可以设置 allowSyntheticDefaultImports 字段为 true,来允许合成默认导入。

(4). esModuleInterop 支持合成默认导入

简单来说,就是支持合成默认导入。

在前端项目开发时,使用 ESM 编写代码引入了 CJS 的模块,由于 CJS 模块没有默认导出内容,因此需要通过我们的工具去自动化合成 CJS 的默认导出,以支持在 ESM 下流畅开发。

esModuleInterop 字段设置为 true 时候,上述提到的 allowSyntheticDefaultImports 字段也会自动设置为 true

moduleResolution 声明如何处理模块

moduleResolution 声明如何处理模块,枚举值:classicnode,会根据 module 字段决定默认值。

推荐手动设置为 node,更符合现在大家的编码认识一些,而且大部分的构建打包工具都是基于 Node。

举个🌰,遇到 import {a} from 'a-lib'; 这样的模块引入代码应该如何去(解析)查找到对应的模块文件。

skipLibCheck 忽略 *.d.ts 声明文件检查

忽略所有的声明文件( *.d.ts)的类型检查

  1. "compilerOptions": {
  2. "skipLibCheck": true
  3. }

这个属性不但可以忽略 npm 不规范带来的报错,还能最大限度的支持类型系统。设置为 true 就不用怕使用的第三方库不规范了。

可能有人好奇,为什么要跳过这些第三方库的检查?

我们做类型检查(以及代码规范等)的目的是为了对团队内业务代码开发保持统一和规范,以保证开发成员之间的快速上手和后续维护。所以我们要做的是将各种规则集成到业务代码模块,而一些框架上的或者第三方库的内容就不用多此一举了。

baseUrl 设置基本目录

baseUrl:设置基本目录以解析非绝对模块名称(定义一个根目录,以此进行绝对文件路径解析)

paths 路径映射列表

paths:用于设置模块名或路径映射列表,这样就可以简写项目中自定义模块的文件路径。

例如在 vue-cli 或者 vite 项目中设置了 alias 路径别名,为了让编译 ts 时也能够解析对应的路径,我们还需要配置 paths 选项

举一个 🌰:

  1. {
  2. "compilerOptions": {
  3. // 注意:baseUrl 必选,与 paths 成对出现,以 tsconfig.json 文件所在目录开始
  4. "baseUrl": ".",
  5. "paths": {
  6. "api/*": ["src/api/*"],
  7. "utils/*": ["src/utils/*"],
  8. "components/*": ["src/components/*"],
  9. "@/*": ["src/*"], // ["./*" ]
  10. "~/*": ["src/*"], // ["./*" ],
  11. },
  12. }
  13. }
  1. // 代码里这么写
  2. import Toast from '@/components/Toast.ts' // 模块实际位置: src/components/Toast.ts
  3. import TestModule from 'moduleA/index.js' // 模块实际位置: src/libs/moduleA/index.js


`

⚠️ 注意: 如果需要自动生成(导出)类型定义文件,TSC 不会处理路径别名,需要引入 typescript-transform-paths插件,以及 TTypescript 来转换路径别名为相对路径。

由于当前的 TypeScript 不支持 tsconfig.json 中的自定义转换器,且无法使用 tsc 命令使用自定义转换器编译文件,所以引入了 TTypescript 作为包装器

`// tsconfig.json
{
“compilerOptions”: {
“baseUrl”: “./“,
// 配置路径别名映射
“paths”: {
“@/“: [“src/“]
},
“plugins”: [
// 转换输出 js 文件中的路径
{“transform”: “typescript-transform-paths”},

// 转换输出 .d.ts 文件中的路径
{“transform”: “typescript-transform-paths”, “afterDeclarations”: true}
]
}
}
`

plugins[10] 是用于扩展 TSC 编译器功能的字段。

例如在 Rollup 打包环境下,可以如下配置:

`import typescript from ‘@rollup/plugin-typescript’;
import ttypescript from ‘ttypescript’;

export default [
{
input: ‘./src/index.ts’,
output: {
dir: ‘dist’,
format: ‘cjs’,
entryFileNames: ‘index.js’,
},
plugins: [
typescript({
typescript: ttypescript,
}),
],
},
];
`

如果是有自动导出类型定义文件的需求,才需要搞这一套插件~

(7). rootDir & outDir

rootDir:指定 TypeScript 识别读取的根目录,用于所有非声明输入文件的最长公共路径

例如:'"rootDir": "./src",则 src 目录下的 TS 文件不能引用 src 目录以外的 ts 文件,一般我们会设置为 ./src./(即 tsconfig.json 所在目录)

outDir:输出目录,即 tsc 编译后的文件输出的文件夹路径(基于 tsconfig.json 文件的相对路径)

例如:"outDir": "./dist",及将 TSC 编译输出的 JS 文件,统一输出的 ./dist 目录下。

(8). jsx

如果是有 jsx 语法需要支持的项目,可以设置值 preservereact

  1. {
  2. "compilerOptions":{
  3. "jsx": "preserve", // 一般 preserve 即可
  4. },
  5. }

(9). importHelpers 从 tslib 库引入语法降级辅助函数

importHelpers 决定是否启用从 tslib 库引入语法降级辅助函数,以避免重复冗余的辅助函数声明。

个人建议是设置为 true 来启用。

(10).experimentalDecorators

experimentalDecorators 用于声明是否启实验性用装饰器模式。

TypeScript 和 ES6 中引入了 Class 的概念,同时在 Decorators[11] 提出了装饰器模式,通过引入装饰器模式,能极大简化书写代码。

当前对于 Decorator 的支持性不太好,如果是一些涉及到使用了装饰器的需要,就需要开启这个属性。

(11). noEmit

noEmit 设置是否输出 js 文件,一般是设置为 false,将打包等工作交给 Webpack 等工具。

三、tsconfig.json 全解析 📚

上面针对 tsconfig.json 中一些常见配置做了详细解释,将一些不常用的配置字段组合在一起,做一个 Checklist 如下:

  1. {
  2. "compilerOptions": {
  3. / 基本选项 /
  4. "target": "es6", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
  5. "module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
  6. "lib": [], // 指定要包含在编译中的库文件
  7. "allowJs": true, // 允许编译 javascript 文件
  8. "checkJs": true, // 报告 javascript 文件中的错误
  9. "jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
  10. "declaration": true, // 生成相应的 '.d.ts' 文件
  11. "declarationDir": "./dist/types", // 生成的 '.d.ts' 文件保存文件夹
  12. "sourceMap": true, // 生成相应的 '.map' 文件
  13. "outFile": "./", // 将输出文件合并为一个文件
  14. "outDir": "./dist", // 指定输出目录
  15. "rootDir": "./", // 用来控制输出目录结构 --outDir.
  16. "removeComments": true, // 删除编译后的所有的注释
  17. "importHelpers": true, // tslib 导入辅助工具函数
  18. "isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).
  19. / 严格的类型检查选项 /
  20. "strict": true, // 启用所有严格类型检查选项
  21. "noImplicitAny": true, // 在表达式和声明上有隐含的 any 类型时报错
  22. "strictNullChecks": true, // 启用严格的 null 检查
  23. "noImplicitThis": true, // this 表达式值为 any 类型的时候,生成一个错误
  24. "alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
  25. / 额外的检查 /
  26. "noUnusedLocals": true, // 有未使用的变量时,抛出错误
  27. "noUnusedParameters": true, // 有未使用的参数时,抛出错误
  28. "noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
  29. "noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch case 语句贯穿)
  30. / 模块解析选项 /
  31. "moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
  32. "baseUrl": "./", // 用于解析非相对模块名称的基础目录
  33. "paths": {}, // 模块名到基于 baseUrl 的路径映射的列表
  34. "rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
  35. "typeRoots": [], // 包含类型声明的文件列表
  36. "types": [], // 需要包含的类型声明文件名列表
  37. "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
  38. "esModuleInterop": true, // 支持合成模块的默认导入
  39. / Source Map Options /
  40. "sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
  41. "mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
  42. "inlineSourceMap": true, // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件
  43. "inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap --sourceMap 属性
  44. / 其他选项 /
  45. "experimentalDecorators": true, // 启用装饰器
  46. "emitDecoratorMetadata": true // 为装饰器提供元数据的支持
  47. },
  48. / 指定编译文件或排除指定编译文件 /
  49. "include": [
  50. "src/**/*"
  51. ],
  52. "exclude": [
  53. "node_modules",
  54. "**/*.spec.ts"
  55. ],
  56. "files": [
  57. "index.ts",
  58. "test.ts"
  59. ],
  60. // 从另一个配置文件里继承配置
  61. "extends": "@tsconfig/recommended",
  62. // IDE 在保存文件的时候根据 tsconfig.json 重新生成文件
  63. "compileOnSave": true // 支持这个特性需要 Visual Studio 2015 TypeScript 1.8.4 以上并且安装 atom-typescript 插件
  64. }

四、打包工具中的 TypeScript 🦁

前文讲到了为什么不推荐直接使用 TSC 作为项目的打包编译工具,那么接下来就简单看看在常见的几款打包工具中针对 TypeScript 的编译方案是如何设计的?

4.1 Rollup + TypeScript

在 Rollup 打包中,我们一般只需要添加 @rollup/plugin-typescript插件即可,该插件会默认读取项目根目录下的 tsconfig.json 配置文件。

Rollup 的配置就像这样:

`// file: rollup.config.js
import typescript from ‘@rollup/plugin-typescript’;

export default {
input: ‘src/index.ts’,
output: {
dir: ‘output’,
format: ‘cjs’
},
plugins: [typescript()]
};
`

结合其源码:

tsconfig.json 编译配置 - 图7

默认使用 TSC 作为 TS 的编译器

因为 typescript 声明了是 peerDependencies,因此会采用项目中安装的 typescript 版本,即是使用我们项目中的 TS 编译器。

通过阅读 @rollup/plugin-typescript 源码,可以看到该插件会默认使我们自己项目中的 tsconfig.json 文件作为 TSC 编译的配置,但会做一些配置预设覆盖:

会调用 ts.parseJsonConfigFileContent() 方法,将 FORCED_COMPILER_OPTIONS 值 merge 到用户的自定义配置中。

tsconfig.json 编译配置 - 图8

FORCED_COMPILER_OPTIONS

通过英文解释看到,因为需要 TSC 编译获得 JS 产物,所以会将 noEmit 设置为 false,也就是 TSC 编译会输出文件,但为什么我们在输出目录却没有看到对应的 TSC 产物呐?

tsconfig.json 编译配置 - 图9

TSC 编译结果存储到内存中

但是如果开启了 declaration,则会将 TSC 解析得到的 *.d.ts 文件输出到指定目录。

4.2 Webpack + TypeScript

在 Webpack 中的 TypeScript 官方文档中,指明了需要安装:typescriptts-loader 两个模块。

配置 Webpack 并支持 TypeScript 的配置如下:

`// file: webpack.config.js
const path = require(‘path’);

module.exports = {
entry: ‘./src/index.ts’,
module: {
rules: [
{
test: /.tsx?$/,
use: ‘ts-loader’,
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [‘.tsx’, ‘.ts’, ‘.js’],
},
output: {
filename: ‘bundle.js’,
path: path.resolve(__dirname, ‘dist’),
},
};
`

可以看出 Webpack 主要是依赖 ts-loader 实现对 TypeScript 语法的编译支持,再看看对 ts-loader 的介绍:

tsconfig.json 编译配置 - 图10

ts-loader

换句话说,ts-loader 实际调用了 TSC 来编译 TS 文件,TSC 的配置依赖于你项目中的 tsconfig.json 文件。

如果使用了 Babel,则可以使用 @babel/preset-typescript 来处理,但 Babel 不会做 TS 类型校验,在打包工具 Rollup 和 Webpack 中都可以引入 Babel,那么接下来看看 Babel 是如何处理 TypeScript 的吧!

4.3 Babel + TypeScript

Babel 处理 TS 需要安装 @babel/preset-typescript 模块,然后在 babel 项目配置文件中声明:

// 配置说明:https://babeljs.io/docs/en/babel-preset-typescript {"presets": ["@babel/preset-typescript"] }

但 Babel 中只会对 TS 代码转为 JS 代码(通过 parse TS 文件为 AST,并直接移除类型信息,然后打印目标代码),不会去做 TS 类型检查,所以 Babel 编译 TS 文件相较于 TSC 的速度更快!

同时,因为 Babel 会根据不同的兼容环境,按需引入 pollyfill,比 TSC 直接引入 core-js 更优雅,因此使用了 Babel 打包的体积也会更小。

TS 类型检查工作可以交给代码编辑器承担,当然同时可以新增 TS 检查的命令:

// package.json { "script": {"tsCheck": "tsc --noEmit",} }

可以把类型检查放到特定的 npm scripts 生命周期之前,另外其实也可以将类型检查放到 git commit 阶段,用于做必要的 TS 类型检查,保证项目的正确性。

4.4 ESbuild + TypeScript

通过 Vite 体会到了 ESbuild[15] 带来的开发热更新 “极速” 体验,针对 TS 项目,ESbuild 和 Babel 是相同的编译策略,即仅编译,不校验类型

ESbuild 处理 TypeScript[16] 同样可以带来飞一般的感觉!

Vite 使用 esbuild 将 TypeScript 转译到 JavaScript,约是 tsc 速度的 20~30 倍,同时 HMR 更新反映到浏览器的时间小于 50ms。—— Vite Docs[17]

但在 ESbuild 中需要启用 tsconfig 中的 isolatedModules 功能,然后在类型引入的时候需要替换,规则参考如下:

`// old
import {UserType} from ‘./types’;

// new
import type {UserType} from ‘./types’;
`

因为 ESbuild 是单独编译每个文件,无法判断引入的是 Type(类型) 还是 值,所以需要开发者显示地声明是 “Type”。

同时还需要启用 esModuleInterop 功能,用于支持 ESM 模块合成默认导入,以兼容 CJS 和 ESM 规范。

另外 ESbuild 不支持:emitDecoratorMetadatconst enum 类型和 *.d.ts 文件

此外,关注到兼容性处理这方面,Bable 和 ESbuild 是类似的,因此会存在兼容性问题:

tsconfig.json 编译配置 - 图11

兼容性

对于装饰器处理不支持,因为 TS 是 JS 的超集,ESnext 的规范提案某些还不是稳定的,因此如果有这方面诉求的项目,可以借助 TSC 做预编译,例如使用 Rollup 的 typescript 插件 或 Webpack 的 ts-loader 方式。

五、总结 📒

另外,tsconfig.json 推荐配置策略如下:

  1. 借助 extends 字段,并结合项目应用场景,继承官方推荐配置
  2. 针对项目特点,按需修改对应功能配置
  3. 建议启用 importHelpersesModuleInterop,取消 noEmit 输出
  4. TS 项目的打包构建,推荐使用 Webpack、Rollup、Bable 等专业工具来保证正确性和构建优化