tsconfig、严格模式、项目引用与工程编译
tsconfig.json 看起来只是几个开关,但它会影响哪些文件被检查、哪些 API 被认为存在,以及代码怎样输出。不要急着复制一份很长的配置。先确定代码在哪里运行,再逐项理解严格检查和模块选项,就能解释为什么需要这些设置。
读配置时按四件事分类:检查哪些文件,提供哪些类型定义,怎样理解模块,最后输出什么。一个开关让报错消失,未必就是正确修复;还要确认它符合项目实际运行的环境。
升级时先看实际配置,不要先关检查
配置文件回答的是“编译器应该怎样理解这个项目”。升级后突然报错,可能是默认值改变,也可能是新检查找到了原来漏掉的问题;两种情况需要不同处理。先运行 npx tsc --version 确认用的是项目版本,再用 npx tsc --showConfig 查看继承完成后的配置。
TypeScript 6.0 发布说明记录了严格检查、全局类型加载和 rootDir 默认行为的变化。一个实用做法是显式指定 strict、types、rootDir,然后逐个解释报错。服务端需要 Node 类型就安装并声明它们;浏览器项目则别为了消除报错把 Node 全局一并带进来。
检查通过后还要运行生成的 JavaScript。类型检查回答“这段代码是否符合已知类型”,运行测试回答“它是否真的做了预期的事”,两者相互补充。这里保留现有练习使用的 5.9.3 基线,没有顺便升级网站自身的编译器或依赖。
1. 文件选择
{
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["dist", "coverage"],
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
}
}
exclude 不是安全边界:被已包含文件导入的模块仍会进入程序。用 npx tsc --explainFiles 检查文件为何被纳入。
2. 严格模式族
strict 开启一组更强检查,未来版本可能向该组增加选项,所以升级后出现新诊断是正常的。重要成员包括:
strictNullChecks:把null/undefined纳入类型。noImplicitAny:不允许无法推断而产生隐式any。strictFunctionTypes:更严格检查函数参数兼容性。strictPropertyInitialization:要求类字段在构造完成前初始化。useUnknownInCatchVariables:catch变量按unknown处理。
3. 推荐的额外防错选项
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noPropertyAccessFromIndexSignature": true
}
}
这些选项可能增加局部代码量,但能让数组越界、可选属性语义、覆写和分支遗漏显式出现。
4. target、module、moduleResolution、lib
{
"compilerOptions": {
"target": "ES2024",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2024"],
"types": ["node"]
}
}
- Node 服务不应无意包含
DOM,否则window会在检查阶段虚假可用。 - 浏览器应用通常包含
DOM,但不应无意包含 Node 全局。 types控制自动注入的@types包;它不限制显式导入的声明。- 不要仅凭“TypeScript 7”这个主版本号猜测默认值。先记录
npx tsc --version的实际结果,再阅读对应发布说明;本章显式写出关键配置,避免依赖版本默认值。
5. 检查与生成分离
{
"scripts": {
"typecheck": "tsc --noEmit",
"build": "tsc -p tsconfig.build.json"
}
}
应用可能由 Vite/SWC 转换源码,而 tsc --noEmit 独立保证类型检查。库通常还需要声明 emit。
6. 配置继承
tsconfig.base.json:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"verbatimModuleSyntax": true
}
}
包配置:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"rootDir": "src",
"outDir": "dist"
},
"include": ["src"]
}
数组型配置通常会替换而非自动合并父配置,应使用 --showConfig 查看最终结果。
7. 项目引用
{
"files": [],
"references": [
{ "path": "./packages/domain" },
{ "path": "./packages/api" }
]
}
npx tsc --build
npx tsc --build --clean
项目引用为大型仓库建立显式依赖和增量构建边界。被引用项目通常启用 composite,公共边界通过声明文件传递。
8. 增量构建与缓存
incremental 产生 .tsbuildinfo 缓存检查图。缓存不是产物真相,CI 缓存键至少包含 TypeScript 版本、配置和锁文件;出现难解差异时清理后全量构建。
9. skipLibCheck 的取舍
它跳过声明文件内部检查,可加快构建并缓解依赖声明冲突,但不会让本项目使用声明时完全无检查。库作者和类型基础设施应优先保持关闭;大型应用若开启,需要跟踪上游问题,避免长期掩盖重复类型版本。
10. 配置诊断命令
npx tsc --showConfig
npx tsc --explainFiles
npx tsc --traceResolution
npx tsc --extendedDiagnostics
参考:TSConfig Reference、strict、Project References、TypeScript 6.0。
11. Freshness metadata
last_verified:2026-08-26version_scope:TypeScript 7.0 / 6.0 migrationsource_type:TypeScript 官方文档stability:fast-moving