首页 / TypeScript 入门教程 / tsconfig.json 详解(上)

TypeScript 入门教程

tsconfig.json 详解(上)

本教程共 80 篇 · 第 5 篇 · 更新于 2026-08-10 · 约 13 分钟阅读

TypeScriptTypeScript 入门教程tsconfigtsc编译选项项目配置extends

本节目标:理解 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 子项(strictNullChecksnoImplicitAny 等)没必要再逐个列出来。module 也直接是 esnext,不再默认 commonjs

TypeScript 7.0 重要变更strict 默认 truemodule 默认 esnexttarget 下限是 ES2015。如果你把旧项目的 tsconfig 原封不动搬到 7.0,注意检查这些字段是否还适用。

tsconfig.json 的顶层结构

一个完整的 tsconfig.json 顶层字段长这样:

{
  "compilerOptions": {},
  "files": [],
  "include": [],
  "exclude": [],
  "extends": "",
  "references": [],
  "watchOptions": {},
  "typeAcquisition": {}
}

其中 compilerOptionsfilesincludeexclude 这四个是你最常用的。extendsreferences 在项目变复杂后会频繁出现。watchOptionstypeAcquisition 相对少见,本章不展开。

files:点名哪些文件要编译

files 是一个字符串数组,每项是一个相对于 tsconfig.json 的文件路径。它的语义很直白——“请编译这几种文件”:

{
  "compilerOptions": {},
  "files": [
    "src/index.ts",
    "src/utils.ts",
    "src/types.d.ts"
  ]
}

files 适合文件数量少、结构固定的场景。一旦项目文件多起来,手写几十个文件路径就不现实了。这时候就该用 include

include 和 exclude:用 glob 管文件范围

includeexclude 用 glob 模式来描述文件范围。它们是 tsconfig.json 里管理文件的主力:

{
  "compilerOptions": {},
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

支持的 glob 语法

TypeScript 支持的 glob 符号有这么几个:

  • * — 匹配零个或多个字符(不包括路径分隔符)
  • ? — 匹配任意单个字符(不包括路径分隔符)
  • **/ — 匹配任意层级的子目录

举几个例子:

模式匹配
src/**/*src 目录及所有子目录下的任意文件
src/**/*.tssrc 目录及所有子目录下的 .ts 文件
src/*.tssrc 目录下的一级 .ts 文件(不含子目录)
**/*.spec.ts任意目录下的 .spec.ts 文件

include 和 exclude 的执行逻辑

tsc 会按这个顺序决定哪些文件参与编译:

  1. 如果写了 files,这些文件一定被包含
  2. include 里的模式会匹配出候选文件
  3. 候选文件再经过 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 的所有配置,只覆盖了 outDirrootDir。省掉了大量样板选项。

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 / strictBindCallApply
  • strictFunctionTypes / strictPropertyInitialization
  • noImplicitAny / noImplicitThis

另外还有不归 strict 管的独立检查项:

  • noImplicitReturns / noFallthroughCasesInSwitch
  • noUnusedLocals / noUnusedParameters
  • noUncheckedIndexedAccess / exactOptionalPropertyTypes

TypeScript 7.0 的 strict 默认就是 true,新建项目不要手动关掉它。

模块(Modules)

决定编译产物使用哪种模块系统,以及怎么解析导入路径:

  • module:输出模块格式。7.0 默认 esnext,可选 commonjsnode16nodenextpreserve
  • moduleResolution:模块解析策略。7.0 支持 bundlernode16nodenext
  • esModuleInterop / allowSyntheticDefaultImports:CommonJS 互操作
  • resolveJsonModule:允许 import JSON 文件
  • isolatedModules:确保每个文件可被独立转译

TypeScript 7.0 重要变更AMDUMDSystemJS 三种模块格式和 moduleResolution: node10 已被移除。用了就会报错。

输出控制(Emit)

决定 tsc 把什么东西放在哪里:

  • outDir:JS 输出目录
  • rootDir:源码根目录
  • sourceMap / declaration / declarationMap:生成 source map 和类型声明
  • noEmit:只检查不产出(CI 常用)
  • removeComments:删除注释

JavaScript 语言特性(Language & Environment)

控制编译产物的 JS 版本和可用的类型库:

  • target:产物 JS 版本。7.0 最低 ES2015,推荐 ES2022ES2023
  • lib:可用的标准库声明(如 "ES2023""DOM"
  • jsx:JSX 处理方式(react-jsxpreservereact-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 三种策略有什么区别。