Skip to main content

tsconfig

对于高级前端来说,不仅仅要会写 TS 语法,还需要理解 TypeScript 编译器的行为(如模块解析策略、严格模式背后的意义、编译目标等)。

作用

  • 用于标识 TypeScript 项目的根路径。
  • 用于配置 TypeScript 编译器(tsc)的行为。
  • 用于指定需要/不需要编译的文件。

重要字段

  • files - 设置要编译的文件的名称;
  • include - 设置需要进行编译的文件,支持路径模式匹配(Glob);
  • exclude - 设置无需进行编译的文件(默认会排除 node_modules);
  • compilerOptions - 设置与编译流程相关的核心选项。
{
"compilerOptions": {
/* 基本选项 */
"target": "es5", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
"module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"lib": [], // 指定要包含在编译中的库文件
"allowJs": true, // 允许编译 javascript 文件
"checkJs": true, // 报告 javascript 文件中的错误
"jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
"declaration": true, // 生成相应的 '.d.ts' 文件
"sourceMap": true, // 生成相应的 '.map' 文件
"outFile": "./", // 将输出文件合并为一个文件
"outDir": "./", // 指定输出目录
"rootDir": "./", // 用来控制输出目录结构 --outDir.
"removeComments": true, // 删除编译后的所有的注释
"noEmit": true, // 不生成输出文件
"importHelpers": true, // 从 tslib 导入辅助工具函数
"isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).

/* 严格的类型检查选项 */
"strict": true, // 启用所有严格类型检查选项(强烈建议开启)
"noImplicitAny": true, // 【重要】不允许出现隐式的 any 类型
"strictNullChecks": true, // 【重要】严格的 null 检查(null 和 undefined 只能赋值给自身、any、unknown 或声明了联合类型的变量)
"noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误
"alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
"strictBindCallApply": true, // 严格检查 bind、call、apply 的参数类型
"strictFunctionTypes": true, // 【高级】严格检查函数类型兼容性(禁用双向协变,要求函数参数严格逆变)

/* 额外的检查 */
"noUnusedLocals": true, // 有未使用的变量时,抛出错误
"noUnusedParameters": true, // 有未使用的参数时,抛出错误
"noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
"noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)

/* 模块解析选项 */
"moduleResolution": "node", // 【面试高频】选择模块解析策略:'node'(从 node_modules 里逐层向上找)或 'classic'
"baseUrl": "./", // 用于解析非相对模块名称的基目录
"paths": {}, // 模块名到基于 baseUrl 的路径映射的列表(常用于配置 alias,如 "@/*": ["src/*"])
"rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
"typeRoots": [], // 包含类型声明的文件夹列表(默认是 node_modules/@types)
"types": [], // 编译时需要额外包含的类型声明文件包(如 ["node", "jest"])
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
"esModuleInterop": true, // 【重要】提供 CommonJS 和 ES 模块之间的互操作性(允许 import React from 'react' 而非 import * as React)

/* Source Map Options */
"sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
"mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
"inlineSourceMap": true, // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件
"inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性

/* 其他选项 */
"experimentalDecorators": true, // 启用装饰器
"emitDecoratorMetadata": true, // 为装饰器提供元数据的支持
"skipLibCheck": true // 【优化性能】跳过所有的 *.d.ts 文件的类型检查(大型项目中必开)
}
}

高级配置:Project References (工程引用)

在大型项目或 Monorepo 架构(如使用 Lerna、pnpm workspace 等)中,把整个项目作为一个单一的 TS 项目编译会非常慢,且不同模块间的边界不清晰。

TypeScript 3.0 引入了 Project References(项目引用)。它允许将一个大的 TypeScript 项目拆分为多个相互依赖的独立较小项目。

如何配置

在主(根)tsconfig.json 中配置 references

{
"compilerOptions": {
// 根目录通常只是为了组合,不需要自己编译文件
"composite": true
},
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/utils" },
{ "path": "./packages/app" }
]
}

在子项目的 tsconfig.json 中,必须开启 composite 选项:

{
"compilerOptions": {
"composite": true,
"declaration": true // 开启 composite 时,declaration 必须为 true
}
}

核心优势

  1. 大幅提升编译速度:通过使用 tsc -b (build) 命令,TS 会像 Make 工具一样,只重新编译发生更改的项目及其依赖项目(增量编译)。
  2. 逻辑隔离:每个项目可以拥有自己独立的 tsconfig.json(比如前端 app 用 DOM lib,后端 Node 服务不引入 DOM lib)。
  3. 强制解耦:子项目之间的引用必须通过编译后的产物(如 distlib 目录),避免了源码层面的面条式依赖。