tsconfig.json 详解(上)
本教程共 80 篇 · 第 5 篇 · 更新于 2026-08-10 · 约 13 分钟阅读
本节目标:理解 tsconfig.json 是怎么来的、管什么的、怎么写。学完你能自己生成、读懂并调整一个项目的 tsconfig 配置文件,看懂 files/include/exclude 的 glob 规则,理解 extends 和 references 的用法。
tsconfig.json 是什么
tsconfig.json 是一个 JSON 格式的配置文件,放在项目根目录下。它的出现意味着这个目录就是一个 TypeScript 项目的根。
你可以把它理解成 tsc 编译器的”遥控器”——第 4 章那些命令行选项(--target、--outDir、--strict),全都可以写在 tsconfig.json 里。命令行的优先级更高,但配置文件才是日常开发的正选。
项目编译时,tsc 会从当前目录开始往上逐级查找 tsconfig.json。找到后就不再往上了。
Note如果你在命令行里指定了输入文件(比如
npx tsc hello.ts),tsc 会直接忽略 tsconfig.json。只有不加文件参数时才会读配置。
npx tsc —init:一键生成
从零开始配 tsconfig.json,最快的方式不是手写——是让 tsc 帮你生成:
npx tsc --init
执行后,项目根目录会多出一个 tsconfig.json。你用 VS Code 打开它,会看到一堆带注释的配置项。TypeScript 7.0.2 默认生成的核心配置大概是这个样子:
{
"compilerOptions": {
"target": "ES2023",
"module": "esnext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"declaration": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src"
}
}
比 TypeScript 6.x 时代的默认配置短了很多。因为 strict 已经是 true 了,那些 strict 子项(strictNullChecks、noImplicitAny 等)没必要再逐个列出来。module 也直接是 esnext,不再默认 commonjs。
TypeScript 7.0 重要变更:
strict默认true、module默认esnext、target下限是ES2015。如果你把旧项目的 tsconfig 原封不动搬到 7.0,注意检查这些字段是否还适用。
tsconfig.json 的顶层结构
一个完整的 tsconfig.json 顶层字段长这样:
{
"compilerOptions": {},
"files": [],
"include": [],
"exclude": [],
"extends": "",
"references": [],
"watchOptions": {},
"typeAcquisition": {}
}
其中 compilerOptions、files、include、exclude 这四个是你最常用的。extends 和 references 在项目变复杂后会频繁出现。watchOptions 和 typeAcquisition 相对少见,本章不展开。
files:点名哪些文件要编译
files 是一个字符串数组,每项是一个相对于 tsconfig.json 的文件路径。它的语义很直白——“请编译这几种文件”:
{
"compilerOptions": {},
"files": [
"src/index.ts",
"src/utils.ts",
"src/types.d.ts"
]
}
files 适合文件数量少、结构固定的场景。一旦项目文件多起来,手写几十个文件路径就不现实了。这时候就该用 include。
include 和 exclude:用 glob 管文件范围
include 和 exclude 用 glob 模式来描述文件范围。它们是 tsconfig.json 里管理文件的主力:
{
"compilerOptions": {},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
支持的 glob 语法
TypeScript 支持的 glob 符号有这么几个:
*— 匹配零个或多个字符(不包括路径分隔符)?— 匹配任意单个字符(不包括路径分隔符)**/— 匹配任意层级的子目录
举几个例子:
| 模式 | 匹配 |
|---|---|
src/**/* | src 目录及所有子目录下的任意文件 |
src/**/*.ts | src 目录及所有子目录下的 .ts 文件 |
src/*.ts | src 目录下的一级 .ts 文件(不含子目录) |
**/*.spec.ts | 任意目录下的 .spec.ts 文件 |
include 和 exclude 的执行逻辑
tsc 会按这个顺序决定哪些文件参与编译:
- 如果写了
files,这些文件一定被包含 include里的模式会匹配出候选文件- 候选文件再经过
exclude的过滤,被 exclude 划掉的文件不会参与编译
你不需要在 exclude 里写 node_modules——TypeScript 默认就会排除它。但如果你的某些模式不小心匹配到了 node_modules 里的东西,显式加上 "exclude": ["node_modules"] 可以兜底。
include 没写时怎么办
如果你既没有写 files 也没有写 include,TypeScript 会把 tsconfig.json 所在目录及其子目录下的所有 .ts、.tsx、.d.ts 文件纳入编译。exclude 仍然生效。
实际项目中强烈建议至少写一个 include。默认全量扫在几百个文件时还能用,文件一多启动就慢得离谱。
extends:继承另一份配置
现实中你很少从零开始写 tsconfig。官方维护了一套基础配置仓库 tsconfig/bases,覆盖了 Node.js、React、Vue 等常见运行环境。
extends 让你直接站在别人的肩膀上:
{
"extends": "@tsconfig/node22/tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}
这个项目继承了 @tsconfig/node22 的所有配置,只覆盖了 outDir 和 rootDir。省掉了大量样板选项。
extends 的值可以指向:
- npm 包名(如
@tsconfig/node22/tsconfig.json)——从node_modules解析 - 相对路径(如
./tsconfig.base.json)——从当前文件所在目录解析
多个配置合并时,子配置的字段会覆盖父配置的同名字段。只有 compilerOptions 是深度合并的(子配置的某个选项覆盖父配置的对应选项,而不是整个替换 compilerOptions)。
一个常见模式是项目里的三层继承:
tsconfig.base.json ← 公共编译选项
↑
tsconfig.build.json ← extends base,加构建选项
↑
tsconfig.json ← extends build,加开发相关选项
references:项目引用
当一个仓库里有多个子项目(monorepo),你可能想让 tsc 知道它们之间的依赖关系。references 做的就是这件事:
{
"compilerOptions": {
"composite": true,
"outDir": "./dist",
"rootDir": "./src"
},
"references": [
{ "path": "../shared" },
{ "path": "../utils" }
]
}
每个引用指向另一个包含 tsconfig.json 的目录。被引用的项目必须设置 "composite": true——这告诉 tsc 这个子项目可以被其他项目引用,并且需要生成 .d.ts 声明文件和构建信息文件(.tsbuildinfo)。
引用项目的典型结构:
packages/
shared/
tsconfig.json ← { "composite": true }
src/
index.ts
app/
tsconfig.json ← { "references": [{ "path": "../shared" }] }
src/
main.ts
编译时用 --build 模式:
npx tsc --build packages/app
tsc 会先检查 shared 是否已构建(通过 .tsbuildinfo 文件),如果没构建或是过期了,就自动先构建依赖项再构建 app。这个流程在大型 monorepo 里节省大量时间。
Tip不要手动维护
.tsbuildinfo文件。它们由 tsc 自动生成和更新,放心加进.gitignore。
compilerOptions 全景概览
compilerOptions 是 tsconfig.json 最大的字段,也是后面第 6 章的重点。这里先做一个分类地图,让你知道有哪些大类,不用背。
类型检查(Strict 家族)
控制类型检查的严格程度。核心就是 strict 这个总开关,它本身是 8 个子选项的合集:
strict/alwaysStrict/strictNullChecks/strictBindCallApplystrictFunctionTypes/strictPropertyInitializationnoImplicitAny/noImplicitThis
另外还有不归 strict 管的独立检查项:
noImplicitReturns/noFallthroughCasesInSwitchnoUnusedLocals/noUnusedParametersnoUncheckedIndexedAccess/exactOptionalPropertyTypes
TypeScript 7.0 的 strict 默认就是 true,新建项目不要手动关掉它。
模块(Modules)
决定编译产物使用哪种模块系统,以及怎么解析导入路径:
module:输出模块格式。7.0 默认esnext,可选commonjs、node16、nodenext、preservemoduleResolution:模块解析策略。7.0 支持bundler、node16、nodenextesModuleInterop/allowSyntheticDefaultImports:CommonJS 互操作resolveJsonModule:允许 import JSON 文件isolatedModules:确保每个文件可被独立转译
TypeScript 7.0 重要变更:
AMD、UMD、SystemJS三种模块格式和moduleResolution: node10已被移除。用了就会报错。
输出控制(Emit)
决定 tsc 把什么东西放在哪里:
outDir:JS 输出目录rootDir:源码根目录sourceMap/declaration/declarationMap:生成 source map 和类型声明noEmit:只检查不产出(CI 常用)removeComments:删除注释
JavaScript 语言特性(Language & Environment)
控制编译产物的 JS 版本和可用的类型库:
target:产物 JS 版本。7.0 最低ES2015,推荐ES2022或ES2023lib:可用的标准库声明(如"ES2023"、"DOM")jsx:JSX 处理方式(react-jsx、preserve、react-native等)
路径与项目组织(Paths & Base URL)
控制导入路径的解析起点和别名:
baseUrl:非相对模块导入的解析根目录paths:路径别名映射("@/*": ["src/*"])rootDirs:多源码目录的虚拟根typeRoots/types:类型声明文件的来源控制。7.0 默认types: []——不再自动加载所有@types/*
兼容与互操作(Interop Constraints)
处理不同模块系统之间的兼容问题:
allowJs:允许编译 JS 文件checkJs:对 JS 文件也做类型检查forceConsistentCasingInFileNames:强制文件名大小写一致skipLibCheck:跳过.d.ts的类型检查(加快编译)
实验性功能(Experimental)
还在演进中的特性:
experimentalDecorators:装饰器支持emitDecoratorMetadata:装饰器元数据useDefineForClassFields:按 ES 标准处理类字段
TypeScript 7.0 新增
7.0 引入的新选项值得单独列出:
stableTypeOrdering:保证并行类型检查的输出稳定,默认开启、不可关闭--checkers N:类型检查 worker 数(命令行参数,默认 4)--builders N:并行项目引用构建的 worker 数(命令行参数)--singleThreaded:关闭所有并行(调试用)
这些并行相关的选项不在 tsconfig 里写,而是通过命令行传入——第 7 章会详细展开。
小结
这一章把 tsconfig.json 的骨架讲完了。总结一下关键点:
tsconfig.json是 TypeScript 项目根目录的标记,也是编译器的配置中心- 用
npx tsc --init生成初始配置,然后按需调整 files精确指定文件,include/exclude用 glob 模式管理范围extends继承现有配置,减少样板代码references+composite解决 monorepo 的项目依赖构建compilerOptions有六大类选项:类型检查、模块、输出、语言特性、路径、兼容
下一章钻进去看 compilerOptions 里面每个关键选项的细节——strict 家族到底检查什么、module 和 target 怎么选、moduleResolution 三种策略有什么区别。