TypeScript tsc 编译命令速查手册
按场景速查 tsc 的全部高频命令:编译与检查、watch 与增量、工程构建、诊断排查,并区分 tsc 与打包器的职责边界。
0. 学习目标(可验证)
- 能区分 tsc 的两种工作模式:命令行传文件模式与 tsconfig 项目模式
- 能用
tsc --noEmit、tsc -w、tsc -b完成检查、监听与工程构建三类任务 - 能说出”哪些命令做类型检查、哪些命令产出文件”,避免与打包器职责混淆
- 会用
--explainFiles、--showConfig、--listFiles排查配置问题
1. 一句话理解
tsc是 TypeScript 的编译器命令行工具:给它文件,它编译文件;给它tsconfig.json,它按配置编译整个项目。日常开发里它的两大角色是”类型检查器”(CI 里跑--noEmit)和”声明文件产出器”,真正的 JS 产物大多交给打包器生成。
2. 两种工作模式(先分清这个)
# 模式一:命令行直接传文件(不看 tsconfig)
tsc main.ts # 编译单个文件,产出 main.js
tsc src/a.ts src/b.ts # 编译多个文件
# 模式二:项目模式(读取 tsconfig.json)
tsc # 编译当前目录的 tsconfig.json
tsc -p ./packages/core # -p 指定配置文件或所在目录
讲解:
- 命令行传文件时,tsc 不读取 tsconfig.json,所有选项都要在命令行给,适合单文件试验;
- 项目模式读 tsconfig(含
extends继承链),是工程的标准用法; - TypeScript 6.0 起,tsconfig.json 存在时再在命令行传文件会直接报错(TS5112);确要临时合并配置可用
tsc --ignoreConfig main.ts(详见typescript/680-TypeScript6And7CompilerEvolution)。
3. 环境初始化与版本确认
npx tsc --init # 生成 tsconfig.json(5.9 起模板大幅精简)
npx tsc --init --strict --module nodenext # 生成时附带初始选项
npx tsc -v # 查看版本,如 Version 7.0.2
npm install -D typescript # 项目内安装(推荐,锁定版本)
讲解:
--init生成的配置自带解释注释;5.9 重写后只保留推荐默认值,其余项指向官方文档;- 项目内安装的
typescript保证团队成员与 CI 用同一编译器版本,全局安装仅推荐练手; tsc --init可多次执行前先备份——它会覆盖已有 tsconfig.json。
4. 类型检查:CI 与本地的第一命令
tsc --noEmit # 只检查类型,不产出任何文件
tsc -p . --noEmit # 项目模式下等价写法
tsc --noEmitOnError # 有类型错误时不写出 JS(默认会写)
tsc --declaration --emitDeclarationOnly # 只产出 .d.ts,不产出 .js
讲解:
--noEmit是 CI 类型检查门禁的标准命令:全量检查、零副作用,配合tsc -v可以在日志里确认编译器版本;- tsc 默认”即使有类型错误也产出 JS”(错误只是报告);
--noEmitOnError让错误阻断产出,语义更接近传统编译器; - 库项目发布前用
--emitDeclarationOnly单独产出声明文件,配合打包器产出的 JS。
5. 编译产出控制
tsc --outDir dist # 产物输出到 dist 目录
tsc --sourceMap # 生成 .map,便于调试映射回 TS 源码
tsc --removeComments # 产物中剔除注释
tsc --declaration # 同步产出 .d.ts
// 产物控制通常写进 tsconfig 而不是命令行
{
"compilerOptions": {
"outDir": "dist",
"sourceMap": true,
"declaration": true,
"declarationMap": true // .d.ts 的 source map,monorepo 跳转友好
}
}
注意——--outFile 已成历史:TS 5.x 的 --outFile(把多个模块合并进单个 JS)在 6.0 已被移除,合并/打包请交给 esbuild、Rollup 等打包器。老脚本里见到 tsc a.ts b.ts --outFile bundle.js 要直接改用打包器。
6. 监听与增量
tsc -w # watch 模式:文件变更即重编译(等价 --watch)
tsc -w --preserveWatchOutput # watch 时不清屏,日志可滚动回看(CI 日志友好)
tsc --incremental # 增量编译:缓存到 .tsbuildinfo,二次构建更快
tsc --incremental --tsBuildInfoFile .cache/ts.tsbuildinfo
讲解:
- watch 模式默认每次输出前清屏,排错时加
--preserveWatchOutput保留历史输出; .tsbuildinfo是纯缓存文件,应加入.gitignore;删除它即可强制回到全量构建;- watch 只服务开发体验;CI 里仍然用一次性的
tsc --noEmit,避免缓存状态差异。
7. 工程构建:tsc -b 与项目引用
// 根 tsconfig.json:声明对子项目的引用
{
"references": [{ "path": "./packages/shared" }, { "path": "./packages/app" }]
}
tsc -b # 按依赖拓扑构建所有引用的项目(等价 --build)
tsc -b --dry # 演练:显示将构建什么,但不写盘
tsc -b --clean # 清理各项目的构建产物
tsc -b --force # 无视缓存强制全量构建
tsc -b --watch # 项目引用下的监听构建
讲解:
tsc -b是 monorepo 的原生构建方案,只重建”过期”的子项目(详见typescript/420-ProjectReferencesMonorepo);- 被引用的项目必须开启
composite: true,这是-b能判断增量的前提; - TS 7.0 为
-b重写了并行的 builders 实现(--builders N可调并行度),大仓构建进一步提速。
8. 高频选项速查(按用途分组)
# 模块系统与目标:决定"产出什么形态的 JS"
tsc --module esnext # 保留 ES 模块语法(打包器项目常用)
tsc --module nodenext # 跟随最新 Node 的模块互操作规则
tsc --module node18 # 冻结为 Node 18 的互操作行为(5.8+)
tsc --target es2022 # 语法降级目标(6.0 起最低 ES2015)
tsc --moduleResolution bundler # 解析策略:bundler / node10(弃用) / node16 / nodenext / classic(已移除)
tsc --lib es2022,dom # 可用的内置类型库
# 严格检查:决定"多严"
tsc --strict # 一组严格选项的总开关
tsc --noImplicitAny --strictNullChecks --noUncheckedIndexedAccess # 常用单项
tsc --exactOptionalPropertyTypes --noImplicitOverride # 进阶单项
# JSX 与特殊语法
tsc --jsx react-jsx # react / react-jsx / preserve / react-native
tsc --erasableSyntaxOnly # 只允许可擦除语法(Node 原生类型剥离友好,5.8+)
tsc --verbatimModuleSyntax # import/export 原样保留,强制用 import type 标注纯类型导入
// 路径别名(写在 tsconfig 里)
{
"compilerOptions": {
"paths": {
"@/*": ["src/*"],
"@core/*": ["packages/core/src/*"]
}
}
}
讲解:
module/moduleResolution/target三件套决定产出的”形态”,strict家族决定检查的”力度”,排错时先确认自己改的是哪一类;verbatimModuleSyntax与”保留 import 断言”无关——它管的是导入语句的形态原样保留(类型导入必须写import type);- 完整的选项语义与推荐组合见
typescript/350-TypeScriptEngineeringConfig与typescript/360-TsconfigStrictMode。
9. 诊断与排查命令
tsc --showConfig # 展开 extends 继承后的"最终生效配置"
tsc --explainFiles # 解释每个文件"为什么被包含"(体积来源、@types 泄漏)
tsc --listFiles # 列出全部参与编译的文件
tsc --diagnostics # 输出编译耗时、内存、文件数等统计
tsc --noCheck # 跳过类型检查但仍完整产出(5.6+,拆分构建与检查)
讲解:
- “编译为什么这么慢/产物为什么这么大”先跑
--explainFiles:测试文件、重复的 @types 包、被main字段带进来的依赖一览无余; --showConfig是排查extends覆盖问题的第一工具——你看到的注释里的配置不一定生效,展开后的才是事实;--noCheck允许”先快速出产物、后台再补检查”的流水线,但 CI 门禁仍必须是完整检查。
10. tsc 与打包器的分工
| 职责 | 负责方 | 原因 |
|---|---|---|
| 类型检查 | tsc(--noEmit) | 只有完整类型系统才能做检查 |
| 代码转换/压缩/按需加载 | Vite、esbuild、SWC | 快,且支持 HMR 等开发特性 |
.d.ts 产出 | tsc(declaration)或打包器插件 | tsc 直接产出最可靠;隔离声明可用 isolatedDeclarations |
| 多模块合并 bundle | 打包器 | --outFile 已移除,tsc 不做打包 |
讲解: Vite 等工具开发态用 esbuild 转译 TS(不做类型检查),所以”浏览器不报错”不等于”类型正确”——CI 的 tsc --noEmit 才是类型层面的最终裁决。
11. 6.0/7.0 视角:命令怎么变
- 命令形态不变:7.0(Go 原生实现)仍是
tsc命令,--noEmit、-w、-b全部照旧,典型全量检查提速 8-12 倍; - 默认值变了:6.0 起
strict默认开启、target默认当年年度 ES 版本、命令行文件与 tsconfig 不可混用——依赖旧默认的脚本要显式补参数; - 双轨工具:迁移期可用
@typescript/typescript6提供的tsc6与 7.x 的tsc并行比对(详见typescript/680-TypeScript6And7CompilerEvolution)。
12. 常见陷阱
陷阱 1:以为 tsc 会打包。 tsc 按入口逐文件转译,不处理打包、压缩与依赖树摇动;需要 bundle 时用打包器,tsc 只负责检查与声明产出。
陷阱 2:CI 忘记 --noEmit。 tsc 在 CI 上会写出 dist 目录,既慢又可能覆盖产物;检查门禁固定写 tsc --noEmit。
陷阱 3:watch 不加 --preserveWatchOutput。 默认清屏导致 CI/远程终端日志丢失,报错”一闪而过”。
陷阱 4:命令行选项与 tsconfig “打架”。 命令行显式给出的选项会覆盖 tsconfig(如 tsc -p . --module commonjs),但仅限少数白名单选项;拿不准就用 --showConfig 看最终值。
13. 动手试试
入门版(必做)
- 新建空目录,
npm i -D typescript后依次执行npx tsc --init、npx tsc -v、npx tsc --noEmit,观察三个命令的输出; - 在 TS 文件里写一行
const x: number = "oops";,跑npx tsc --noEmit,确认报错位置与错误码(TS2322); - 把
--showConfig加到tsc --init生成的项目上,对照展开后的配置。
进阶版(选做)
- 给项目加
tsc -w --preserveWatchOutput,故意改错类型再改回来,观察增量输出; - 在有两个
references的最小 monorepo 上跑tsc -b --dry、tsc -b --force,对比缓存命中时的构建清单; - 用
--explainFiles找出项目里”不该参与编译”的文件,并在 tsconfig 中排除它们。
14. 小结
初学者记住这三点:
tsc --init建配置,tsc --noEmit做检查,tsc -w边写边查——起步只要这三条;- tsc 管”检查”和”声明产出”,不管打包;产物交给打包器;
- 报配置问题时先跑
tsc --showConfig和tsc --explainFiles,让编译器告诉你”它眼里的事实”。
进阶者还需注意:
--outFile已随 6.0 移除、命令行文件与 tsconfig 不可混用(--ignoreConfig除外)、moduleResolution: node10/classic已弃用或移除——老脚本迁移时逐一核对;- CI 门禁用一次性
--noEmit全量检查,本地开发用 watch/增量,--noCheck只用于”产物先行”的流水线; - 升级到 TS 7 后命令不变、默认并行(
--checkers/--builders可调),老 CI 脚本无需改动即可享受提速。