- 引言 — 7月8日,tsgo 变成了 tsc
- 先把数字搞准 — 到底测的是什么
- "10倍"是有旋钮的 — --checkers
- 真正的成本(1) — TypeScript 6 的全部废弃预告变成了硬错误
- 真正的成本(2) — 没有 API,所以 Vue、MDX、Astro、Svelte 今天还搬不了
- 让 6 和 7 共存 — tsc6 与 npm 别名
- 悄悄改变的地方 — JSDoc 与 Unicode
- 那么,你今天该不该迁移
- 结语
- 参考资料
引言 — 7月8日,tsgo 变成了 tsc
2026 年 7 月 8 日,TypeScript 7.0 正式 GA。跑了 1 年多预览版的 Go 原生移植版进入了正式发布。
如果你过去 1 年一直在关注这个项目,tsgo 这个名字你应该很熟悉。此前它作为独立包(@typescript/native-preview)、独立二进制发布 nightly 版本,和现有的 tsc 并排跑是标准做法。到了 GA,这套格局消失了。 官方公告里一次都没出现 tsgo 这个词。取而代之的是这样的说法 — 执行 npm install -D typescript 装进来的就是"新的 tsc 可执行文件"。
也就是说,原生移植版不再是可选项,而是默认值。直接查 npm 注册表可以看到,typescript 的 latest 标签是 7.0.2,发布日期是 2026 年 7 月 8 日 — 与公告里的 GA 日期完全一致。而 @typescript/native-preview 的最后一次发布停在 7 月 7 日,也就是 GA 前一天。nightly 版本现在已经转移到了 typescript@next(目前是 7.1.0-dev 系列)。
发布时间线是这样走的 — beta 4 月 21 日,RC 6 月 18 日,GA 7 月 8 日。
本文不是要重新论证"Go 移植版很快"这件事。这一点已经在TypeScript 6 与 tsc-go 移植版一文里、以预览版时期为基准讲过了,说实话,当时设想的发布形态(像 tsc --go 这样的后端标志、一个大版本同时出货两个编译器)和实际的 GA 并不一样。实际情况是,大版本本身直接分裂了 — 6 是 JS 实现,7 是 Go 实现。本文只依据 GA 时确定下来的事实,看看标题数字背后真正的迁移成本。
先把数字搞准 — 到底测的是什么
公告自己的说法是 "10x faster native port",正文里有条件的那句是这样写的 — 原生代码速度、共享内存多线程、以及若干优化,在完整构建(full builds)上通常能带来 8 倍到 12 倍的速度提升。
这是 Microsoft 亲自测量并公开的完整构建耗时表。这是厂商自己报告的数字,在同一台机器上用 TypeScript 7 的默认设置测出来的。
代码库 TS 6 TS 7 速度提升
vscode 125.7s 10.6s 11.9x
sentry 139.8s 15.7s 8.9x
bluesky 24.3s 2.8s 8.7x
playwright 12.8s 1.47s 8.7x
tldraw 11.2s 1.46s 7.7x
有两点值得注意。第一,表里的下限是 7.7 倍,比"8~12 倍"这个自我表述略低。第二,速度提升因代码库而异 — vscode 的 11.9 倍和 tldraw 的 7.7 倍相差 1.5 倍。看起来代码库越大,并行化收益越大。
内存数据也一并公开了,而这恰恰是应该降低预期的地方。
代码库 TS 6 TS 7 变化
vscode 5.2GB 4.2GB -18%
sentry 4.9GB 4.6GB -6%
bluesky 1.8GB 1.3GB -26%
playwright 1.0GB 0.9GB -11%
tldraw 0.6GB 0.5GB -15%
这和预览期流传的"内存减半"说法不一样。实际的 GA 数字是下降 6% 到 26%,sentry 几乎原地踏步。相比速度跳了一个数量级,内存只是温和改善。公告自己的说法也只到"通常在完整构建中需要更少的总内存"为止,没有再多主张。
编辑器这边也有数字。在 VS Code 代码库中打开一个有错误的文件,看到第一个错误出现,同一台机器上以前大约要 17.5 秒,TypeScript 7 上不到 1.3 秒 — 也就是快了 13 倍以上。
作为企业案例报告的数字需要更谨慎地读一层。这些是 Microsoft 表示是从各团队那里听来的数值。
- Slack — CI 类型检查时间从约 7.5 分钟降到 1.25 分钟。据称合并队列时间因此消失了 40%。此前由于编辑器语言服务器的加载时间,本地开发几乎"没法用",工程师们把整体类型检查都甩给了 CI,现在同一个代码库据称几秒就能加载完。
- Canva — 编辑器里看到第一个错误的时间从约 58 秒降到约 4.8 秒。
- Vanta — 在其最大的一个项目上最高达到 9 倍。
- Microsoft News Services 团队 — 每月节省了原本花在等待 CI 构建上的 400 小时。
还有稳定性数字。Microsoft 表示,根据自家数据洞察,7.0 的新语言服务器相比 6.0,把失败的语言服务器命令减少了 80% 以上,服务器崩溃减少了 60% 以上。这是基于遥测的自我测量,不是外部能够复现的那类数字。
"10倍"是有旋钮的 — --checkers
这是 GA 才揭晓、而且大多数摘要文章都漏掉的部分。那些基准数字,是某个特定并行化设置下的结果。
TypeScript 7.0 把解析、类型检查、生成(emit)并行执行。解析和生成按文件几乎相互独立,所以并行化效果很好。问题出在类型检查上 — 文件之间的依赖很复杂,大多数文件都要依赖同一个全局作用域和依赖项的类型信息。而且类型检查有时还依赖程序内信息的相对顺序,要让结果保持一致,就必须始终按同样的顺序检查。
于是 TypeScript 7 会创建固定数量的类型检查器 worker。每个 worker 都有自己的一套世界观,会重复做一部分公共工作,但只要输入相同,就总是以同样的方式切分文件,产出同样的结果。
默认的 worker 数量是 4。前面的表全都是用默认的 --checkers 4 测的,公告还在同一台机器上用 --checkers 8 重新测了一遍,把表格并排放了出来。
代码库 TS 6 TS 7 (--checkers 8) 速度提升
vscode 125.7s 7.51s 16.7x
sentry 139.8s 12.08s 11.6x
bluesky 24.3s 2.01s 12.1x
playwright 12.8s 1.16s 11x
tldraw 11.2s 1.06s 10.6x
把检查器数量提到 8,vscode 能到 16.7 倍。但这不是免费的 — 用公告自己的话说,增加检查器数量通常要付出内存占用增加的代价。而且结果会因项目和机器而异。
方向也可以反过来。在 CPU 核心和内存较少的环境里 — 公告直接举的例子就是 CI runner — 反而可能应该调低这个值,避免不必要的开销。可以一路调到 --checkers 1,这样类型检查实际上就变成单线程,重复工作也就消失了。
这里出现了实务上最重要的一句话。
极少数情况下,改变
--checkers的数量可能会暴露出依赖顺序的结果差异。
也就是说,团队自己承认了检查器数量可能影响诊断结果。公告的建议是在整个构建环境中固定一个检查器数量,让所有人拿到相同的结果,但也补充说这终究是团队自己的裁量。如果本地是 8、CI 是 2 这样各自为政,原理上就为"我机器上能过,CI 上报错"这种情况留了口子。换作是我,无论是 tsconfig.json 还是 CI 脚本,我都会把这个值钉死在一个地方。
还有两个相关的标志。--builders 用来调节 --build 模式下同时运行的项目引用构建器数量(面向 monorepo)。要注意的是它和 --checkers 是相乘关系 — 就照公告自己的例子,--checkers 4 --builders 4 允许最多 16 个类型检查器同时运行,这可能会过头。--singleThreaded 会彻底关掉并行化(用于调试、比较 6 和 7 的性能、由外部工具协调并行构建的场景,或资源极其紧张的环境)。--checkers 和 --builders 目前都是作为实验性(experimental)标志引入的。
和 --checkers 不同,文档明确说明改变 --builders 的数量不应改变结果。相反,项目引用构建从根本上会被项目依赖图卡住瓶颈。
真正的成本(1) — TypeScript 6 的全部废弃预告变成了硬错误
接下来是该付钱的部分了。
兼容性本身是好的。公告里带条件的那句是这样写的 — 在打开 stableTypeOrdering 标志、且未设置 ignoreDeprecations 标志的情况下,能在 TypeScript 6.0 下干净编译的代码,几乎不管是什么,在 7.0 下都应该能同样编译通过。
问题就出在这个前提上。7.0 原样采纳了 6.0 的新默认值,并且对 6.0 里已经预告要废弃的标志和语法给出硬错误。正如公告自己承认的,"6.0 相对还比较新,很多项目还需要适应它的新行为"。所以官方的建议是不要直接跳到 7,而是先引入 6.0,让迁移更顺畅。
先看默认值的变化。
strict -> 默认 true
module -> 默认 esnext
target -> esnext 之前最近的稳定 ECMAScript 版本
noUncheckedSideEffectImports -> 默认 true
libReplacement -> 默认 false
stableTypeOrdering -> 默认 true,且无法关闭
rootDir -> 默认 ./ (内部源码目录需要显式指定)
types -> 默认 [] (以前的行为是 ["*"])
公告里点名的"最令人意外"的变更是 rootDir 和 types 这两个。两者都很容易缓解。tsconfig.json 位于 src 这类目录之外的项目,只要想保留目录结构,显式指定 rootDir 就行。
{
"compilerOptions": {
"rootDir": "./src"
},
"include": ["./src"]
}
types 这边,依赖全局声明的项目需要自己列出所需的内容。
{
"compilerOptions": {
"types": ["node", "jest"]
}
}
看起来无害,但这恰恰是个安静的地雷。types 默认值变成 [] 之后,自动探测就关掉了 — 如果你此前只是装上 @types/node 或 @types/jest,指望它们被自动捡起来,在 7 上会突然冒出一堆"找不到全局符号"的报错。不是代码错了,是配置变了,修法也只是一行,但在一个大型 monorepo 里逐包踩一遍,是件挺磨人的活。
strict 默认变成 true 也是同样的道理。对一个一直以 non-strict 方式生存下来的旧代码库来说,这不是"换个编译器",而是"重写类型"。为了换来一个快 8 倍的编译器,可能得先预付几个月的 strictNullChecks 工作量。
还有彻底消失的东西 — 不是空操作(no-op),是硬错误。
target: es5支持终止downlevelIteration支持终止moduleResolution: node及node10支持终止(推荐nodenext或bundler)module: amd、umd、systemjs、none支持终止(推荐esnext或preserve)baseUrl支持终止(把paths更新为相对于项目根目录的相对路径)moduleResolution: classic支持终止esModuleInterop与allowSyntheticDefaultImports不能设为falsealwaysStrict始终被视为 true,不能设为false- 命名空间声明中不能使用
module关键字 - import 中不能使用
asserts关键字 — 要按 ECMAScript import attribute 语法改用with - 在
skipDefaultLibCheck下,/// <reference no-default-lib />指令不再被遵循 - 当前目录存在
tsconfig.json时,命令行构建无法再接受文件路径(除非显式传入--ignoreConfig标志)
这份清单里,最让实务疼痛的是 baseUrl 和 target: es5。baseUrl 广泛埋在旧项目的绝对路径 import 里,而 target: es5 对还必须支持旧版浏览器的团队来说,可能是一个不可谈判的要求。如果需要 es5,7 就不属于你。这不是靠改改配置就能跨过去的那种墙。
最后一条也出乎意料地容易踩到。不少团队把 npx tsc src/foo.ts 这类命令写进了脚本里,而只要项目根目录存在 tsconfig.json,现在就直接报错。
真正的成本(2) — 没有 API,所以 Vue、MDX、Astro、Svelte 今天还搬不了
这是 GA 公告里最重要、却被引用得最少的部分。
TypeScript 7.0 出了,但不出货 API。
没有编程 API。公告写道,预计会在 7.1 中出货一个新的(而且不同的)API,在那之前,优先事项是让 6 和 7 能够并排运行。
影响是直接的。照搬公告"TypeScript and Embedded Languages"一节的说法 — 使用 Vue、MDX、Astro、Svelte 等的工作流,很可能暂时还用不上 TypeScript 7。 像 Angular 那种模板内部的专门类型检查也是一样。原因是 7 还没有暴露出稳定的编程 API,所以那些把 TypeScript 嵌入自己编译器和语言服务里的工具 — 比如 Volar — 目前只能依赖 TypeScript 6.0。
这不是"可能会慢一点",而是用不了。前端生态系统相当大的一块都卡在这里。Vue 团队、Astro 团队、Svelte 团队,以及所有基于 MDX 的文档/博客流水线,全都架在 Volar 之上。
建议因此分成了几类。
- 在不需要语言服务器插件的场景下使用 7 — 这是基本建议。
- Angular — 可以组合使用:CLI 里用
tsc做快速的项目级错误检测,编辑器支持则用 6.0。也就是说能拿到半份收益。 - Vue、MDX、Astro、Svelte 等 — 目前还得继续用 6.0。在 VS Code 里可以用"Disable TypeScript 7 Language Server"命令切回 6.0。
Microsoft 把这看作一个"特定时间点的问题(point-in-time issue)",承诺会提供解决方案,并表示会积极和相关项目的维护者合作。我认为这是一个可信的承诺 — 但承诺修不好今天的构建。 从 7.1 的新 API 出炉,到 Volar 移植适配,再到 Vue/Astro/Svelte 各自的工具链跟进采用,中间要经过好几个发布周期。公告自己透露的发布节奏是每 3 到 4 个月一次,下游采用的时间还要再叠加上去。
让 6 和 7 共存 — tsc6 与 npm 别名
所以现实的答案通常是"两个都留着"。为此 Microsoft 新出了一个兼容包。
@typescript/typescript6 提供了一个叫 tsc6 的可执行文件。这样一来,它就能和自带 tsc 二进制的 7.0 并排安装,而不会撞名。这个包还重新导出了 TypeScript 6.0 的 API,所以你可以让 tsc 用 7,同时让其他工具链继续依赖 6.0。查 npm 注册表可以看到,这个包的 latest 是 6.0.2,bin 字段正好只有一项:tsc6。
像 typescript-eslint 这样的工具,是通过 peer dependency 期望直接从 typescript 里 import 的,所以推荐的做法是用 npm 别名。
npm install -D typescript@npm:@typescript/typescript6
不过只做这一步,留下的就只有 tsc6 这个可执行文件。要想同时拿到 7.0 的 tsc,还得再加一个别名。
{
"devDependencies": {
"@typescript/native": "npm:typescript@^7.0.2",
"typescript": "npm:@typescript/typescript6@^6.0.2"
}
}
这样一来,npx tsc 跑的是 7.0,而那些 import typescript 的工具看到的是 6.0。
说实话,这不是一个优雅的解法。package.json 里绞在一起两个别名,typescript 这个名字实际指向的却是 6,第一次看到的人肯定会懵。但如果你在用 typescript-eslint,又想让 tsc 跑得快 — 也就是现实中相当一部分项目的处境 — 目前这就是官方路径。
悄悄改变的地方 — JSDoc 与 Unicode
被性能标题盖过去了,但确实可能破坏代码的变更还有两处。
JavaScript 支持被重做了。 原本 TypeScript 是通过识别 JSDoc 注释和特定代码模式来支持 JS 文件的,这经常是一堆基于 Closure 或 JSDoc 文档生成工具理解方式的特例。7.0 把这部分重写成和 .ts 文件的分析方式保持一致。结果是有些东西消失了。
- 不能在类型该出现的位置写值 — 要写成
typeof someValue @enum不再享有特殊待遇- 不能把单独的
?当类型用 — 用any @class不会再把函数变成构造函数 — 要用类声明- 不支持后置
! - 类型名必须在
@typedef标签内部定义(放在标识符旁边的写法不再允许) - 不支持 Closure 风格的函数语法 — 用 TypeScript 的简写形式
给 this 起别名,或者整体重新赋值函数原型的这类模式,也失去了特殊处理。如果你有一个用 JSDoc 标注类型的大型 JS 代码库,这里才是真正的迁移工作量所在。TypeScript 团队表示他们另外维护着一份记录 6.0 和 7.0 差异的 CHANGES.md 文件,并把 JS 支持描述为仍"处于变动中(in flux)"。
模板字面量类型现在会保留 Unicode 码点。
type HeadTail<S> = S extends `${infer Head}${infer Tail}` ? [Head, Tail] : never;
type Result = HeadTail<"😀abc">;
// 在 7.0 中: ["😀", "abc"]
// 此前: ["\ud83d", "\ude00abc"]
以前是按照 JavaScript 的 UTF-16 索引行为,把代理对(surrogate pair)从中间切开。技术上这和 JS 的索引方式是一致的,但通常并非本意,还可能产生带着没有意义的、落单代理项的字符串字面量类型。新的行为和用 for...of 遍历或展开(spread)时的直觉是一致的。
公告很诚实地把这标记为一次针对刻意建模 UTF-16 code unit 的类型级字符串操作的破坏性变更 — 举的例子是一些字符串 Length 工具类型。如果你在使用或构建做深度类型级字符串编程的库,需要检查一下。
还有一点。--watch 模式被彻底重做了。新的基础是把 Parcel 打包器的文件监视器移植到了 Go(原本是 C++,需要一整套 C++ 工具链,现在用一个最小的汇编垫片把它搬到了 Go)。原因是 Go 标准库没有文件监视 API,而基于轮询的方案在 node_modules 依赖很多的大型项目上代价太高。公告报告说,--watch 在各平台上的资源占用都有大幅改善。
那么,你今天该不该迁移
归纳起来是这样。
今天迁移值回票价的情况
- 已经在用 TypeScript 6.0,打开
stableTypeOrdering、没有设置ignoreDeprecations也能干净构建 — 这正是官方兼容性声明所保证的确切条件。这种情况下,迁移基本上很顺畅。 - 纯
.ts/.tsx代码库,且不使用 Volar 系的嵌入式语言工具链。 - CI 类型检查是真正的瓶颈 — 8 倍在这里能直接变现。
- 编辑器的响应速度是团队实实在在的痛点。
目前还搬不了的情况
- 在用 Vue、MDX、Astro、Svelte — 这不是选择题。得等 7.1 的 API,以及随后的 Volar 移植。
- Angular — 只能拿到一半。CLI 类型检查用 7,编辑器用 6。
- 需要
target: es5— 是一堵墙。 - 还在 TypeScript 5.x,且是 non-strict — 不要直接跳到 7。先经过 6 是官方建议,而且是有理由的:与其一次性踩完整份废弃清单,不如在 6 里以警告的形式逐步清理。
- typescript-eslint 这类依赖 API 的工具链是核心工作流 — 靠前面那套别名组合是可行的,但这份复杂度值不值得承担,得由团队自己判断。
再说一条关于顺序的建议。如果要迁移,从一开始就明确固定 --checkers 的值。 本地和 CI 跑在不同的默认并行度下,一旦碰上依赖顺序的诊断差异,那是最不想调试的一类 bug。既然团队自己都写明"极少数情况下可能暴露出来",把值钉死的成本是一行代码,不钉死的成本是大半天。
结语
TypeScript 7.0 的性能故事是真的。虽然是厂商自报,但是拿可复现的开源代码库测出来的,条件(默认 --checkers 4、完整构建)也公开了,甚至还把 --checkers 8 的表格一并放出来,自己就说明了数字会随配置变动。做到这个程度,作为厂商基准测试已经算诚实的了。如果 Slack 那种从 7.5 分钟到 1.25 分钟的数字能复现,在大代码库上,这就是生活质量问题。
但标题是"快了 10 倍",而真实的故事是"快了 10 倍,代价是要把 6 的整份废弃清单清算干净,而且前端生态里很大一块,在 API 出来之前都还没被邀请入场"。
所以我是这么看的 — 7.0 是一次已经开始、但还没完成的迁移。 在 7.1 带着 API 出现、Volar 站上去之前,这个生态系统还得有一阵子分裂成 6 和 7 两边生活。@typescript/typescript6 和 tsc6 这类兼容包的存在本身,就是对这一点的承认。Microsoft 自己也清楚这一点,所以公告的结尾写道,希望"用 7.1 补上任何缺口,把社区带向前"。
如果你是纯 TS 代码库,今天是个好日子。如果你站在 Vue 或 Astro 之上,这次发布暂时还不属于你 — 而这不是因为你做错了什么。
参考资料
- Announcing TypeScript 7.0 (Microsoft, 2026-07-08) — 本文所有数字与引述的出处
- Announcing TypeScript 7.0 RC (2026-06-18)
- Announcing TypeScript 7.0 Beta (2026-04-21)
- npm — typescript — GA 时
latest是 7.0.2,next是 7.1.0-dev 系列 - npm — @typescript/typescript6 — 提供
tsc6可执行文件的 6.0 兼容包 - microsoft/typescript-go — 原生移植版仓库
- TypeScript 6 与 tsc-go 移植版 — 预览版时期的相关文章
현재 단락 (1/151)
2026 年 7 月 8 日,[TypeScript 7.0 正式 GA](https://devblogs.microsoft.com/typescript/announcing-typescrip...