阮一峰《TypeScript 教程》学习笔记——tsconfig.json 文件
1. 一段话总结
tsconfig.json是TypeScript项目的根目录配置文件,供tsc编译器使用,可通过tsc --init自动生成,支持通过extends属性继承其他配置(如@tsconfig/npm模块或本地基础配置);核心包含一级属性(include/exclude指定编译文件范围、files列具体编译文件、references引用子项目等)和compilerOptions(控制编译行为,如target指定输出JS版本、module指定模块格式、strict开启严格类型检查、outDir指定产物目录等);JS项目对应jsconfig.json,配置规则与tsconfig.json完全一致,仅用于处理JavaScript源码。
2. 思维导图

3. 详细总结
一、tsconfig.json 文件基础
-
定义与作用
- 是TypeScript项目的根目录标识文件,编译器通过它识别项目范围;若项目为JavaScript,配置文件名为jsconfig.json,语法完全一致。
- 核心功能:指定编译文件范围、控制编译行为(如输出格式、类型检查严格度)、引用子项目等,供
tsc编译器使用。
-
生成与继承
- 自动生成:执行
tsc --init命令,生成含默认注释的配置文件,包含常用compilerOptions选项; - 配置继承:通过
extends属性继承其他配置,减少重复配置,支持两种来源:- 本地文件:如
"extends": "../tsconfig.base.json"(继承上级目录的基础配置); - npm模块:如
"extends": "@tsconfig/node16/tsconfig.json"(需先安装模块,如npm i -D @tsconfig/node16);
- 本地文件:如
- 继承规则:先加载父配置,子配置中重名属性会覆盖父配置。
- 自动生成:执行
-
编译器查找逻辑
- 自动查找:
tsc默认从当前目录向上递归搜索tsconfig.json; - 手动指定:通过
tsc -p 路径指定配置文件或其所在目录(如tsc -p ./src)。
- 自动查找:
二、核心一级属性详解
一级属性直接位于tsconfig.json根对象下,控制编译文件范围和项目依赖,关键属性如下表:
| 一级属性 | 核心作用 | 语法示例 | 关键说明 |
|---|---|---|---|
| include | 指定需编译的文件/目录(支持通配符) | "include": ["src/**/*", "tests/**/*"] | 通配符规则: - ?:匹配单个字符;- *:匹配任意字符(不含路径分隔符);- **:匹配任意目录层级;默认包含:.ts/.tsx/.d.ts,开启 allowJs则含.js/.jsx |
| exclude | 从include中排除文件/目录 | "exclude": ["**/*.spec.ts", "node_modules"] | 需与include配合使用,支持相同通配符;默认排除node_modules、dist等编译产物目录 |
| extends | 继承其他tsconfig配置文件 | "extends": "@tsconfig/recommended/tsconfig.json" | 父配置路径非./或../时,编译器从node_modules目录查找 |
| files | 列出具体需编译的文件(无通配符) | "files": ["src/index.ts", "src/utils.ts"] | 若文件不存在,编译直接报错;适用于文件极少的场景,文件多时不如include灵活 |
| references | 引用子项目(大项目分拆为多个子项目) | "references": [{ "path": "../subproj" }, { "path": "../subproj2/tsconfig.json" }] | 子项目必须开启compilerOptions.composite: true,实现增量构建 |
三、compilerOptions 核心二级属性(按功能分类)
compilerOptions是最复杂的配置项,控制编译行为,按功能分为4类,关键属性如下表:
| 功能分类 | 属性名 | 核心作用 | 关键说明 |
|---|---|---|---|
| 模块与解析 | module | 指定编译产物的模块格式 | 可选值:none/commonjs/es6/es2022/node16/nodenext;默认值: target为ES3/ES5时为commonjs,否则为对应ES版本(如target=es2022→module=es2022) |
| moduleResolution | 模块定位算法(如何查找import的模块) | 可选值:node(Node.js CommonJS逻辑)、node16/nodenext(Node.js ES模块逻辑)、classic(旧算法,不推荐);默认值: module为node16/nodenext时同module,否则为node | |
| baseUrl | 模块查找的基准目录 | 必须与paths配合使用;默认以tsconfig.json所在目录为基准;示例:"baseUrl": "./src" | |
| paths | 模块路径映射(简化长路径导入) | 基于baseUrl解析;示例:"paths": { "@utils/*": ["utils/*"] },导入@utils/foo对应src/utils/foo.ts | |
| 类型检查 | strict | 开启所有严格类型检查(总开关) | 等价开启7个子选项:alwaysStrict/noImplicitAny/noImplicitThis/strictBindCallApply/strictFunctionTypes/strictNullChecks/strictPropertyInitialization;支持单独关闭子选项(如 "strict": true, "alwaysStrict": false) |
| noImplicitAny | 禁止变量/参数被隐式推断为any | strict开启时默认true;若变量无类型且无法推断,编译报错(需显式声明类型) | |
| strictNullChecks | 严格检查null和undefined | strict开启时默认true;需显式判断空值(如if (x !== null)),否则无法调用属性/方法 | |
| strictPropertyInitialization | 类的实例属性必须初始化 | 需配合strictNullChecks;未初始化需用!非空断言(如username!: string)或设为undefined(如`username: string | |
| 输出配置 | outDir | 指定编译产物的存放目录 | 默认为源文件同级目录;示例:"outDir": "./dist",编译后文件输出到dist目录 |
| outFile | 将所有非模块文件合并为单个输出文件 | 仅支持module为None/System/AMD;不支持CommonJS/ES模块(因模块需独立加载) | |
| declaration | 为每个.ts文件生成对应的.d.ts类型声明文件 | 需开启;配合declarationDir: "./types"可指定声明文件目录 | |
| sourceMap | 生成SourceMap文件(关联源码与编译后代码) | 便于调试;inlineSourceMap: true可将SourceMap嵌入JS文件,不单独生成.map文件 | |
| 其他配置 | target | 指定编译产物的JavaScript版本 | 可选值:es3/es5/es6/es2022/esnext;默认es3;版本过老可能不支持箭头函数、let等语法 |
| lib | 加载TypeScript内置的类型描述文件 | 示例:"lib": ["dom", "es2021"],加载DOM API和ES2021语法的类型定义;默认根据target自动加载 | |
| jsx | 处理.tsx文件(React等框架场景) | 可选值: - preserve:保留JSX语法,输出.tsx→.jsx;- react:将JSX转为React.createElement,输出.tsx→.js;- react-native:保留JSX,输出.tsx→.js | |
| allowJs/checkJs | 允许加载JS文件/对JS文件进行类型检查 | checkJs: true会自动开启allowJs;等价于在JS文件顶部添加// @ts-check注释 |
4. 关键问题
问题1:compilerOptions.strict属性的核心作用是什么?它包含哪些关键子选项?若需关闭其中某个子选项,该如何配置?
答案:
- 核心作用:
strict是TypeScript的“严格类型检查总开关”,值为布尔值,开启后会强制启用所有严格类型检查规则,从编译阶段规避潜在的类型安全问题(如隐式any、null引用错误等),是保证代码质量的关键配置,默认关闭。 - 包含的关键子选项(共7个):
alwaysStrict:强制代码以ECMAScript严格模式("use strict")解析;noImplicitAny:禁止变量/参数被隐式推断为any类型;noImplicitThis:当this被推断为any时编译报错(避免this指向模糊);strictBindCallApply:严格检查函数call()/bind()/apply()的参数类型与函数定义匹配;strictFunctionTypes:严格检查函数参数的兼容性(子类型函数不能替代父类型函数);strictNullChecks:严格检查null和undefined,需显式判断空值后才能使用属性/方法;strictPropertyInitialization:类的实例属性必须初始化(需配合strictNullChecks)。
- 单独关闭子选项:在
strict: true的基础上,显式将目标子选项设为false,示例:{"compilerOptions": {"strict": true,"alwaysStrict": false, // 关闭严格模式解析"strictPropertyInitialization": false // 关闭类属性初始化检查} }
问题2:module与moduleResolution两个属性的关系是什么?它们的默认值分别由什么因素决定?
答案:
-
关系:两者紧密关联,共同控制“模块的输出格式”与“模块的查找逻辑”:
module:定义编译产物的模块格式(如CommonJS、ES6),决定代码最终如何被运行时加载(如Node.js加载CommonJS模块,浏览器加载ES模块);moduleResolution:定义编译器如何查找import的模块文件(如import { foo } from './foo'如何定位到foo.ts),算法需与模块格式匹配才能确保正确解析(如Node.js模块需用node算法)。
-
默认值规则:
module的默认值:由target属性决定——- 若
target为ES3或ES5,默认commonjs(因旧JS环境仅支持CommonJS); - 若
target为ES6及以上(如ES2022),默认与target版本一致(如target=es2022→module=es2022)。
- 若
moduleResolution的默认值:由module属性决定——- 若
module为node16或nodenext(Node.js ES模块模式),默认同module(即node16或nodenext); - 若
module为AMD/UMD/System/ES6,默认classic(TS旧算法,不推荐新项目使用); - 其他情况(如
module=commonjs),默认node(Node.js的CommonJS模块查找算法)。
- 若
问题3:include、exclude与files三个一级属性在功能和适用场景上有何核心区别?
答案:
三者均用于控制“哪些文件参与编译”,核心区别体现在灵活性(是否支持通配符) 和精度(是否需列具体文件),适用场景完全不同:
| 属性 | 核心功能差异 | 通配符支持 | 适用场景 | 优缺点 |
|---|---|---|---|---|
| include | 指定文件/目录模式,批量匹配文件 | 支持(?/*/**) | 大多数场景,如“编译src下所有文件”(["src/**/*"]) | 优点:灵活高效;缺点:无法精确控制单个文件 |
| exclude | 从include匹配的文件中排除部分 | 支持(同include) | 排除测试文件(["**/*.spec.ts"])或依赖目录(["node_modules"]) | 优点:精准过滤;缺点:需配合include使用 |
| files | 逐一列出具体参与编译的文件,无模式匹配 | 不支持 | 文件极少的场景,如“仅编译index.ts和config.ts”(["src/index.ts", "src/config.ts"]) | 优点:精度极高;缺点:文件多时繁琐,易遗漏 |
关键对比示例:
- 若项目有100个文件,需编译
src下所有文件但排除测试文件:用include: ["src/**/*"]+exclude: ["src/**/*.spec.ts"]; - 若项目仅需编译2个核心文件:用
files: ["src/index.ts", "src/utils.ts"],避免误编译其他文件。
