TypeScript tsconfig 配置
tsconfig.json 是每个 TS 项目的"控制中枢"——它决定 tsc 怎么编译、用哪些类型库、严格到什么程度。配置项有几十个,但实际常用的就十几个。这一章把必须懂的几个核心选项讲清楚,并给出新项目推荐配置。
1. tsconfig.json 的整体结构
每个 TS 项目根目录放一个 tsconfig.json。它分三大块:compilerOptions(编译选项)、include(哪些文件参与编译)、exclude(哪些文件排除):
// tsconfig.json —— 每个TS项目的"控制中枢"
// 它告诉 tsc:编译成什么 JS、用哪些类型库、严格到什么程度
{
"compilerOptions": {
"target": "ES2020", // 编译成哪个版本的 JS
"module": "ESNext", // 输出哪种模块系统
"moduleResolution": "bundler",// 模块解析策略
"lib": ["ES2020", "DOM"], // 启用哪些类型库
"strict": true, // 开启所有严格检查(强烈推荐)
"outDir": "./dist", // 编译输出目录
"rootDir": "./src", // 源代码根目录
"esModuleInterop": true, // 兼容 CommonJS 的默认导入
"skipLibCheck": true, // 跳过 .d.ts 的类型检查(加快速度)
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"], // 哪些文件参与编译
"exclude": ["node_modules", "dist"]
}2. strict:最重要的选项
strict: true 一次性开启所有严格类型检查。这是新项目必开的选项——它能把 TS 的价值发挥到最大,挡住大量隐性 bug。它会等价于开启下面这一长串子选项:
// strict 是最重要的选项,新项目必开
// 它等价于一次性开启下面所有严格检查:
{
"strict": true,
// 等价于单独配置这些(都不用再写,strict 已包含):
// "noImplicitAny": true, // 禁止隐式 any
// "strictNullChecks": true, // null/undefined 必须显式处理
// "strictFunctionTypes": true, // 严格的函数类型检查
// "strictBindCallApply": true, // 严格的 bind/call/apply
// "strictPropertyInitialization": true, // 类属性必须初始化
// "noImplicitThis": true, // 禁止不明确的 this
// "alwaysStrict": true // 输出 "use strict"
}
// 强烈推荐再加这一条(不在 strict 内,但很值得开)
{
"noUncheckedIndexedAccess": true // arr[0] 的类型是 T | undefined
}其中最关键的是 strictNullChecks——它强制你显式处理 null/undefined,挡住了 JS 里最经典的"undefined is not a function"崩溃。强烈推荐再额外开 noUncheckedIndexedAccess,让数组下标访问(如 arr[0])返回 T | undefined,防止"取到 undefined 还以为是 T"的 bug。
3. target 与 lib
target 决定编译成哪个版本的 JS——版本越低,TS 会把新语法降级翻译成老语法。lib 决定能用哪些全局 API 的类型:
// target:编译成哪个版本的 JS
// 选低版本:TS 会把新语法"降级翻译"成老语法(如箭头函数→普通函数)
{
"target": "ES5", // 兼容古董浏览器(IE)
"target": "ES2020", // 现代浏览器主流(推荐)
"target": "ESNext", // 最新(假设运行环境支持所有新特性)
}
// lib:启用哪些类型库(决定能用哪些全局 API 的类型)
{
"lib": ["ES2020", "DOM"]
// ES2020 提供 Promise.allSettled、BigInt 等的类型
// DOM 提供 document、window、HTMLElement 等的类型
// (Node 项目要装 @types/node,无需在 lib 里写 "Node")
}实战经验:target 选 ES2020(现代浏览器都支持),lib 加上 DOM(前端项目需要 DOM 类型)。Node 项目不需要 DOM,但要装 @types/node。
4. module 与 moduleResolution
这两个决定模块系统和模块解析策略:
// module:输出哪种模块系统
{
"module": "CommonJS", // Node 老标准(require)
"module": "ESNext", // ESM(import,推荐,配合打包工具)
"module": "NodeNext", // Node 新版原生 ESM
}
// moduleResolution:模块解析策略(怎么根据路径找文件)
{
"moduleResolution": "node", // 旧版 Node 规则
"moduleResolution": "bundler", // 配合 Vite/Webpack 等(推荐)
"moduleResolution": "nodenext" // Node 新版
}
// 实战:前端项目(Vite/Next.js)推荐
{
"module": "ESNext",
"moduleResolution": "bundler"
}前端项目用 Vite/Webpack 打包的,推荐 module: ESNext + moduleResolution: bundler——这是当下最顺的组合。
5. 其他常用选项
这些选项在实战中也很高频:路径别名、JSON 导入、sourceMap 等:
// 其他常用选项
{
// 路径别名(用 @/ 代替 src/)
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
// 允许 JS 文件(JS/TS 混用,迁移期有用)
"allowJs": true,
"checkJs": false, // 是否检查 JS 文件的类型
// 源码映射(调试时能看到 .ts 而不是 .js)
"sourceMap": true,
// 不输出编译结果(只做类型检查,编译交给 Vite/esbuild)
"noEmit": true,
// 解析 JSON 文件的 import
"resolveJsonModule": true
}注意 noEmit: true——如果你用 Vite/esbuild 来打包编译,tsc 只负责类型检查(不产出 JS),这时就该开 noEmit。
6. 新项目推荐配置
给你一个开箱即用的前端(Vite/Next.js)配置,复制即用:
// 新项目推荐配置(前端 + Vite)
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true, // 编译交给 Vite
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true
},
"include": ["src"]
}这份配置的特点:现代模块系统 + 最严格的类型检查 + 编译交给打包工具(tsc 只做检查)。新项目直接用,能少踩很多坑。
7. 怎么验证配置生效?
在项目根目录运行 tsc --noEmit,它会按 tsconfig.json 全量检查类型、报出所有错误,但不产出文件。这是 CI 和提交前检查的标配命令。配合 tsx 运行、Vite 开发,构成完整的 TS 工作流。
小结
tsconfig 的核心选项:strict(必开)、target(编译目标,ES2020)、lib(类型库,前端加 DOM)、module + moduleResolution(模块系统)。再加 noUncheckedIndexedAccess 让类型更严密。新项目直接抄最后一节推荐配置。至此,TypeScript 系列 15 篇全部完成——你已经掌握了从语法到工程化的全部核心,恭喜!
← 上一篇 TypeScript 类型断言与守卫
← 返回 TypeScript 教程目录