MLog
返回文章列表
技术#TypeScript#Go#前端#编译器

TypeScript 7.0 发布:Go 重写完成,编译速度提升 12 倍

发布于: 2026年7月14日阅读时长: 9 min

TypeScript 7.0 正式发布,编译器用 Go 重写后编译速度提升 8-12 倍,内存反而更低。一篇个人视角的解读。

TypeScript 7.0 在 7 月 8 号正式发布了。这不是一次普通的 major 版本升级——微软用 Go 把整个编译器重写了一遍。

我关注这个事有一阵子了。去年微软宣布 Go 移植计划的时候,很多人觉得这是个遥远的实验项目。结果不到一年,7.0 RC 就在 6 月 18 号出来了,然后一个月不到稳定版就发了。这个推进速度比我想象的快得多。

不是"优化",是换材料

TypeScript 编译器(tsc)一直是用 TypeScript 自己写的。自举编译器在语言圈里很常见,但问题是 JavaScript 的性能天花板实在有点低——单线程、GC 停顿、大内存开销——这些对编译器这种 CPU 密集型任务来说都是硬伤。

团队在 2023 到 2025 年做了大量优化,比如 --build 模式改进、isolatedDeclarations 等等。但用 Daniel Rosenwasser(TypeScript PM)的话说,这些都是在 JS 引擎的"天花板"下面修修补补。

Go 重写是直接换了一间屋子。共享内存并行、原生编译速度、goroutine 并发模型——这些 JavaScript 运行时根本给不了。

有一点值得强调:团队没有"重新设计"类型检查逻辑,而是直译了原有的 TypeScript 实现。所以你升级后不会看到类型行为有任何变化,该报的错还是报,该过的还是过。纯粹是换了个更快的引擎。

性能数字

TS 6 编译时间 vs TS 7(4 checkers):

项目 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

开到 8 个 checker,vscode 能冲到 16.7 倍。

更有意思的是内存。TS 6 给 vscode 编译峰值吃 5.2GB,TS 7 降到 4.2GB,少了 18%。bluesky 从 1.8GB 降到 1.3GB,少了 26%。又快又省内存,这种"双赢"在软件优化里不算常见。

编辑器体验的提升更直观。以前在 VS Code 自己的代码库里打开一个文件,从打开到看到第一个红色波浪线大概要 17.5 秒——够你站起来倒杯水再回来。现在 1.3 秒以内,超过 13 倍。不是"快了",是"不需要等了"。

并行化模型

TS 7 新增了两个 CLI 参数:

  • --checkers:控制类型检查 worker 数,默认 4
  • --builders:控制项目引用并行构建数

类型检查的并行化有个有意思的难点——文件之间有类型依赖。不能简单地把不同文件分给不同线程各跑各的。TS 7 的方案是:每个 worker 有自己独立的类型视图,可能有少量重复计算,但只要划分策略一致,结果始终是确定的。

另外还提供了一个 --singleThreaded 标志,方便调试和资源受限环境。

一个"疯狂的工程决定"

--watch 模式的重写过程挺有意思的。

Go 标准库没有内置文件系统监听 API。团队试了第三方库,跨平台支持不理想。后来发现 VS Code 用了多年的 @parcel/watcher 非常稳——但它是 C++ 写的。引入 C++ 工具链来编译,跟 Go 单一二进制分发的理念冲突。

所以他们做了一个挺疯的决定:把 Parcel watcher 从 C++ 移植到 Go,只保留极少量汇编 shim。从直译开始,逐步重构为地道的 Go 代码,同时跑通了原版的测试套件。Devon Govett(Parcel 作者)在致谢名单里被特别提及。

升级注意事项

TS 7 继承了 TS 6 的所有默认值变更,并把 TS 6 中标记废弃的配置项升级成了硬错误。主要影响:

  • target: es5 不支持了
  • moduleResolution: node / node10 不支持了,用 nodenextbundler
  • module: amd / umd / systemjs 不支持了
  • baseUrl 不支持了
  • strict 默认 true
  • types 默认空数组(以前自动加载所有 @types/*,现在要手动声明)
  • rootDir 默认 "./"(源目录在 src/ 下需要显式指定)

最后两条影响最广。如果你之前习惯了 npm i -D @types/node 之后什么都不配就能用,现在需要:

{
  "compilerOptions": {
    "types": ["node"]
  }
}

官方建议先升到 TS 6 再迁移到 7,这样配置层面的坑可以分两次踩,不至于一次性面对太多变更。

另外,由于 TS 7.0 没有稳定 API(要等到 7.1),依赖 typescript 包的生态工具(typescript-eslint、ts-jest 等)暂时只能继续用 TS 6。官方提供了 @typescript/typescript6 兼容包,可以用 npm alias 让两个版本共存。Vue、Svelte、Astro、MDX 这些嵌入式语言框架的编辑器集成也要等到 7.1。

他们给的数据还挺实在——TS 7 的语言服务器命令失败率比 6.0 少了 80% 以上,崩溃率低了 60% 以上。

更大的图景

TypeScript 不是第一个"逃离 JS"的核心基础设施。esbuild、Bun、Oxc、Rspack、Rolldown——这个名单越来越长。原因是系统性的:编译器、打包器、linter 这些工具的性能天花板在 JS 运行时里已经碰壁了,而它们恰好又是 CPU 密集型 + 高度可并行的理想工作负载。

有趣的是 TypeScript 选了 Go 而不是 Rust。我的理解是:Go 的简单性、编译速度和 goroutine 并发模型让移植成本更低。TS 团队不是"重写"类型系统,而是"翻译"它——Go 更容易做这种同构移植,不需要面对 Rust borrow checker 的摩擦。

Slack 的工程师反馈说,他们之前因为语言服务器太慢,几乎放弃了本地类型检查,全靠 CI。TS 7 让同一个代码库的加载时间降到几秒,本地类型检查重新变得可行。合并队列等待时间减少了 40%。Canva 的编辑器首次错误提示从 58 秒降到 4.8 秒。微软 News Services 团队每月省下 400 小时 CI 等待。

最后

TS 7 不是一次"特性发布"。它用行动表明:JavaScript 生态的基础设施瓶颈可以突破,方法是换一种语言构建基础设施——但保留你熟悉的一切。

升级清单很简单:先升到 TS 6 把配置理顺,然后装 TS 7,如果没有用 Vue/Svelte/Astro 这类嵌入式框架,应该可以直接用。类型行为不变,只是变快。快很多。