TypeScript 7 已正式切换到 Go 原生编译器,但升级不只是换一个版本号。本文结合官方说明与实际运行结果,拆解新默认配置、稳定 API 缺口、编辑器兼容和并行检查四个关键边界,并给出 TypeScript 6/7 双版本验证方案。
配套验证代码:github.com/xiaogao007/...
bash
git clone https://github.com/xiaogao007/running-404-code-labs.git
cd running-404-code-labs/typescript-7-migration
npm ci
npm run verify
npm install -D typescript,现在安装到的已经是 TypeScript 7。
这次变化很大:tsc 和语言服务不再建立在原来的 JavaScript 代码库上,而是迁移到了 Go 原生实现。官方在 VS Code、Sentry、Playwright、tldraw 等大型开源项目上的完整构建测试中,给出了 7.7 倍到 11.9 倍的加速结果。1
但如果你正准备打开 package.json,把 typescript 改成 ^7.0.2,先别急着提交。
TypeScript 7 的迁移风险,主要不在业务代码,而在编译配置、工具链 API、编辑器插件和 CI 资源。
先给结论:
- 普通 React、Node.js 或不依赖 TypeScript 编译器 API 的项目,可以开始在独立分支验证 TypeScript 7。
- Vue、Svelte、Astro、MDX,以及依赖 Angular 模板类型检查的项目,不建议只改版本号后直接合并。
- 维护 ESLint 插件、代码生成器、AST 工具或自定义构建插件的团队,应该先保留 TypeScript 6 的稳定 API。
- 大型 Monorepo 不要上来就把并行数拉满,先测 CPU、内存和 CI 账单。
下面把原因讲清楚。
TypeScript 7 到底换了什么?
TypeScript 过去一直是一个"自己编译自己"的项目:编译器使用 TypeScript 编写,再编译成 JavaScript 运行在 Node.js 中。
TypeScript 7 把编译器和语言服务迁移到了 Go。官方强调,这不是重新设计一门语言,而是尽量保留旧代码库的结构和类型检查逻辑,同时获得原生代码、多线程和共享内存带来的性能空间。1
速度提升覆盖的不只是 tsc:
- 解析、类型检查和代码生成可以并行执行。
- 项目引用可以并行构建。
--watch使用重建后的跨平台文件监听机制。- 新语言服务基于 LSP,可以并行处理编辑器请求。
官方公布的 7.7 倍到 11.9 倍是特定机器、特定开源项目上的结果,不是所有业务项目的保底收益。本文也没有复刻同规模基准,因此不把官方数据写成"本地实测"。
对大多数团队来说,比速度更重要的是下面四个迁移问题。
坑一:你升级的不只是 7.0,还有 6.0 的新默认值
TypeScript 6 是旧编译器到新编译器之间的过渡版本。很多为了 7.0 做的配置调整,已经先在 6.0 中出现;到了 7.0,部分废弃选项不再只是警告,而是直接报错。12
例如,下面这份老配置在 TypeScript 7 中会失败:
json
{
"compilerOptions": {
"target": "ES5",
"module": "CommonJS"
}
}
本文实际运行得到:
text
error TS5108: Option 'target=ES5' has been removed.
除了 target: ES5,moduleResolution: node10、moduleResolution: classic、baseUrl、outFile、downlevelIteration 以及部分旧模块格式也进入了迁移清单。TypeScript 6 还能通过 ignoreDeprecations 暂时忽略一部分提醒,TypeScript 7 不再支持这些已废弃配置。2
更容易被忽略的是默认值变化:
strict默认变为true。module默认变为esnext。target默认指向当前年度 ECMAScript 版本。types默认变为空数组。- 使用
tsconfig.json时,rootDir不再按旧方式推断公共源码目录。
如果项目依赖 Node.js 全局类型,建议明确写出来:
json
{
"compilerOptions": {
"strict": true,
"target": "ES2025",
"module": "Preserve",
"moduleResolution": "Bundler",
"rootDir": "./src",
"types": ["node"]
},
"include": ["src"]
}
在验证工程中,删除 types: ["node"] 后,即使已经安装 @types/node,引用 process.env 仍然会收到 TS2591;省略 rootDir 并配置 outDir 时,则收到 TS5011,要求显式声明源码根目录。
这类报错不应该用 skipLibCheck 或一串忽略项压过去。更稳妥的处理是把运行环境、产物目录和全局类型依赖写清楚。
坑二:7.0 有 CLI,但还没有稳定的编译器 API
很多前端工具并不是调用 tsc 命令,而是直接执行:
js
const ts = require("typescript");
const program = ts.createProgram({
rootNames: ["src/index.ts"],
options: {}
});
TypeScript 7.0 的默认包入口只暴露版本信息,不提供过去那套稳定的 createProgram API。官方计划在 7.1 提供一套新的、不同的 API;7.0 虽然已经存在标记为 unstable 的子路径,但它们不应该被当成稳定兼容层。13
这个变化会影响两类工具:
- 直接嵌入 TypeScript 编译器的 AST、Lint、代码生成和构建工具。
- 需要把 TypeScript 语言服务嵌入模板的框架插件。
官方在 7.0 公告中明确提醒:Vue、MDX、Astro、Svelte 等工作流目前可能还不能完整利用 TypeScript 7;Angular 项目可以尝试让 CLI 使用 7.0 做项目级检查,同时让编辑器继续使用 6.0 完成模板相关能力。1
这里的判断不是"这些框架不支持 TypeScript 7 语法",而是它们的工具链可能依赖尚未稳定的新 API。两者不能混为一谈。
坑三:命令行升级成功,不代表编辑器链路已经升级
团队常见的验证方式是:
bash
npx tsc --noEmit
命令退出码是 0,就认为升级结束。
但 TypeScript 开发体验至少有两条链路:
text
CI / 构建脚本 -> tsc
编辑器 -> Language Server -> 框架插件
TypeScript 7 使用新的 LSP 语言服务。发布初期,VS Code 需要安装 TypeScript 团队提供的专用扩展;其他编辑器也要分别确认语言服务器接入状态。1
因此,迁移验收不能只看 CI,还要检查:
- 自动补全、跳转、重命名和查找引用是否正常。
- Vue、Svelte、Astro、MDX 或 Angular 模板中的类型提示是否仍然工作。
- 编辑器报告的 TypeScript 版本是否与命令行一致。
- 出现问题时,是否可以快速退回 TypeScript 6 语言服务。
如果团队大量依赖框架模板插件,最稳妥的方案不是"一次切完",而是让 CLI 和编辑器分阶段迁移。
坑四:并行不是越多越好
TypeScript 7 默认使用 4 个类型检查工作进程,并提供三个新的实验性参数:1
bash
tsc --checkers 4
tsc --build --checkers 4 --builders 2
tsc --singleThreaded
--checkers控制并行类型检查进程数量。--builders控制同时构建多少个项目引用。--singleThreaded用于单线程调试、对比或资源受限环境。
真正需要留意的是乘法效应。
如果设置 --checkers 4 --builders 4,同时运行的类型检查器最多可能达到 16 个。对核心数充足的开发机,这可能有利;对只有少量 CPU 和内存的 CI Runner,则可能带来额外调度和内存压力。1
建议先从默认值开始,分别记录:
- 完整检查耗时。
- 峰值内存。
- CI Runner 的 CPU 核数。
- 项目引用数量和依赖图。
- 连续多次运行的波动。
只有这些数据都拿到以后,才值得调整并行参数。不要把"原生多线程"理解成"参数越大越快"。
一套可回退的 TypeScript 6/7 双版本方案
对于依赖编译器 API、框架插件或复杂 Monorepo 的项目,可以暂时让两个版本并存。
官方提供了 @typescript/typescript6 兼容包,并建议通过 npm alias 避免二进制命名冲突:1
json
{
"devDependencies": {
"@typescript/native": "npm:typescript@^7.0.2",
"typescript": "npm:@typescript/typescript6@^6.0.2"
},
"scripts": {
"check:ts7": "tsc --noEmit -p tsconfig.json",
"check:ts6": "tsc6 --noEmit -p tsconfig.json"
}
}
这样可以形成两条明确路径:
bash
npm run check:ts7
npm run check:ts6
tsc使用 TypeScript 7 原生 CLI。tsc6使用 TypeScript 6 兼容 CLI。require("typescript")仍能为旧工具提供 TypeScript 6 的稳定 API。
本文验证工程中,两条命令对同一份源码都检查通过;TypeScript 7 默认包入口的 createProgram 为 undefined,而 TypeScript 6 兼容包仍可正常调用该 API。
这套方案不是长期架构,而是迁移期的隔离带。等依赖工具明确适配 TypeScript 7 的稳定 API 后,再删除兼容包。
本文实际验证了什么?
代码状态:已运行。
验证环境:
text
Windows
Node.js 25.8.2
npm 11.9.0
TypeScript 7.0.2
TypeScript 6 兼容 CLI:运行时报告 6.0.3
@types/node 26.1.2
验证结果:
| 场景 | 结果 |
|---|---|
显式配置 rootDir 与 types |
TypeScript 6/7 均检查通过 |
| 未声明 Node 全局类型 | TypeScript 7 返回 TS2591 |
使用 target: ES5 |
TypeScript 7 返回 TS5108 |
配置 outDir 但未明确 rootDir |
TypeScript 7 返回 TS5011 |
默认导入 TypeScript 7 后读取 createProgram |
结果为 undefined |
| 从兼容包导入 TypeScript 6 API | createProgram 可用 |
验证过程中还遇到一个值得记录的依赖问题:旧版 @types/node@24.1.0 与当前 TypeScript 7 标准库中的 URLPattern 声明发生冲突;升级到验证时最新的 @types/node@26.1.2 后通过。这个结果只能说明该版本组合存在冲突,不能据此推断所有旧版 Node 类型包都不兼容。
本文没有对大型业务项目执行性能基准,因此官方性能数字只用于说明变化规模,不作为本文实测结论。
团队应该按什么顺序升级?
推荐按下面的顺序推进:
第一步:先让项目在 TypeScript 6 下干净通过
处理废弃选项、新默认值和 stableTypeOrdering 暴露的问题。不要同时跨越 5.x、6.x、7.x 后再猜错误来自哪一层。
第二步:固定迁移基线
记录当前 tsc --noEmit 结果、声明文件差异、构建产物目录、编辑器功能和 CI 耗时。
第三步:在独立分支引入 TypeScript 7
先使用默认并行策略,不修改 --checkers 和 --builders。普通项目优先验证 CLI,框架项目同时验证模板插件。
第四步:有 API 依赖就启用双版本
不要用不稳定 API 强行重写生产工具。先保留 TypeScript 6 兼容包,给工具链升级留出时间。
第五步:最后再做性能调优
只有在稳定性、类型结果和编辑器链路都通过后,再根据 CPU、内存和项目引用图调整并行参数。
最后的判断
TypeScript 7 值得关注,不只是因为它更快,而是类型检查第一次真正拥有了面向多核机器的实现基础。
但"编译器正式发布"和"整个前端生态已经完成迁移"是两件事。
对普通 React 或 Node.js 项目,TypeScript 7 已经值得进入验证分支;对依赖框架模板、编译器 API和复杂插件链路的项目,双版本共存不是保守,而是当前更可控的工程选择。
升级的目标也不应该只是让 package.json 看起来更新,而是确保命令行、编辑器、CI 和构建插件仍然对同一份代码给出一致结果。
我是404星球的猫
拒绝当工具人,做 AI 时代的代码架构师。
漫游继续,我们下篇见~
关注我,手握这份 AI 时代的全栈漫游指南