TypeScript 7.0 正式发布:Go 原生编译器到位,大型代码库构建快 10 倍

TypeScript 7.0 正式发布:Go 原生编译器到位,大型代码库构建快 10 倍

TypeScriptJavaScript编程语言微软Go开源

数据源:HN + Lobsters

TypeScript 7.0 在 2026 年 7 月 8 日正式 GA。这是 TypeScript 历史上幅度最大的一次架构变更——编译器从 TypeScript(JavaScript)完整移植到 Go,代号「Project Corsa」。官方宣称全量构建加速 8-12 倍,编辑器反馈延迟从十几秒降到一秒出头。HN 讨论 636 分、250 条评论,社区的情绪是兴奋与实用主义的混合。

不是又一个版本号,是编译器换了一颗心脏

TypeScript 从 2012 年发布以来,编译器始终是 TypeScript 写的——编译自己,然后生成 JavaScript。这个自举的架构在中小型项目上够用,但一旦代码库规模突破某个阈值,类型检查的等待时间就开始挤压开发反馈循环。

2025 年,Anders Hejlsberg 的团队宣布了「Project Corsa」:用 Go 重写 TypeScript 编译器。这个决策背后有几个工程判断。Go 提供原生编译、共享内存多线程、可预测的 GC 行为,这三者结合起来让真正的并行类型检查成为可能。JavaScript 版本受限于单线程和 V8 的内存模型,并行化只能做到文件级的解析和生成,核心的类型推导链路始终是串行的。

Daniel Rosenwasser 在公告中这样描述这次移植的策略:

This port was done as faithfully as possible, writing new code while maintaining the structure and logic of the original codebase to keep results consistent and compatible between the two compilers.

这意味着新编译器采取了「照着旧代码用 Go 重新实现」的策略——结构、逻辑、甚至很多函数名都保持了对应关系。这种做法的缺点是工程量大、周期长,优点是类型检查行为几乎完全一致——TS7 不会悄悄地改变你的类型推导结果

10 倍加速,具体数字在哪里

公告里给出了五个开源项目的全量构建对比。以下数据在同一台机器上测得,TS6 和 TS7 均使用默认配置。

代码库TypeScript 6TypeScript 7加速比
vscode125.7s10.6s11.9x
sentry139.8s15.7s8.9x
bluesky24.3s2.8s8.7x
playwright12.8s1.47s8.7x
tldraw11.2s1.46s7.7x

TS6 与 TS7 构建时间对比

在内存占用方面,TS7 也表现出 6% 到 26% 的下降。对 CI 环境来说,这两个维度同时改善意味着可以用更低规格的 runner 跑更快的构建。

编辑器场景的改善更加直观。以 VS Code 自身代码库为例,从打开一个包含错误的文件到看到红色波浪线,TS6 需要约 17.5 秒,TS7 降到 1.3 秒以内——超过 13 倍的提升。这个数字背后是一套全新的 LSP 实现,它能够利用多线程同时处理多个请求。官方数据显示,新语言服务器的失败命令减少了 80% 以上,服务端崩溃减少了 60% 以上。

TS6 与 TS7 内存使用对比

多线程调参:—checkers 和 —builders

并行化不是免费的。TS7 引入了两个新的实验性 flags 供团队调节:

  • --checkers:控制类型检查的并行 worker 数量,默认 4。类型检查的并行化比文件解析复杂得多——不同文件之间存在依赖关系,完全独立地检查每个文件会重复大量计算。TS7 的做法是创建固定数量的 worker,每个 worker 维护自己的类型视图,在保证相同输入产生相同输出的前提下分摊负载。

  • --builders:控制项目引用(project references)构建时的并行数量。对 monorepo 尤其有用——多个子项目可以同时构建。

两个 flags 有乘数效应。--checkers 4 --builders 4 意味着最多 16 个类型检查器同时运行。在公告的测试中,将 --checkers 从默认的 4 提升到 8,vscode 的全量构建时间进一步从 10.6s 降到 7.51s,加速比达到 16.7x。但更多线程意味着更高的内存占用,需要在 CI runner 的配置里找到平衡点。

另外,--singleThreaded 标志可以将所有并行化关闭,这在调试或对比性能时非常有用。

没有 API 的发布:一个务实的缺口

TS7.0 最引人注意的限制是它不提供可编程 API。typescript-eslint、ts-morph、ts-node 这些依赖编译器内部 API 的工具,目前无法直接使用 TS7。官方在公告中坦率地写道:

While TypeScript 7.0 is here, it does not ship with an API. We expect TypeScript 7.1 to ship with a new (and different) API.

解决方式是并列安装。微软发布了一个兼容包 @typescript/typescript6,它提供了 TS6 的完整 API 和一个名为 tsc6 的可执行文件。项目可以这样做:

{
  "devDependencies": {
    "@typescript/native": "npm:typescript@^7.0.2",
    "typescript": "npm:@typescript/typescript6@^6.0.2"
  }
}

这样 npx tsc 默认使用 TS7 进行类型检查,而 typescript-eslint 等工具仍然通过 typescript 别名拿到 TS6 的 JavaScript API。

这种「双编译器共存」的策略是一种务实的折中。它让大型团队可以先在 CLI 和 CI 中上线 TS7 的速度红利,编辑器端也可以切换到 TS7 的语言服务,而 linting 和代码生成管线可以暂时留在 TS6 上,等 7.1 的 API 就绪再迁移。

不过,对嵌入 TypeScript 的框架来说,这个限制的影响更直接。Vue、Svelte、Astro、MDX、Angular 模板类型检查——这些场景在 TS7.0 中暂时无法工作。它们依赖 Volar 等工具将 TypeScript 编译器嵌入自己的流水线,目前只能继续使用 TS6。Angular 项目可以走一条折中路径:CLI 类型检查用 TS7,编辑器语言服务用 TS6。但对于其他嵌入式框架,整个工具链都需要等 TS7.1 的 API。官方表示正在与这些项目的维护者合作,但这确实是当前迁移决策中需要正视的硬约束。

Breaking Changes:从 TS5.x 升级需要两步走

TS7.0 的直接升级路径是从 TS6.0 来。如果你的项目已经在 TS6.0 上干净编译(stableTypeOrdering 开启、没有 ignoreDeprecations),迁移到 TS7 应该零改动。

但从 TS5.x 升级是两步的过程:先升级到 TS6,处理完所有废弃警告,再迁移到 TS7。TS6 在 2026 年 3 月发布,定位就是一座「桥梁」——把所有在 TS7 中成为硬错误的配置和语法提前标记为废弃。

值得关注的默认值变更:

  • strict 默认为 true。如果你的 tsconfig 没有显式设置 strict,TS7 会按最严格模式运行。
  • target 默认值提升到 esnext 之前的 ECMAScript 稳定版本;es5 不再支持。
  • moduleResolution: node / node10 不再支持,建议切换到 nodenextbundler
  • module: amd / umd / systemjs / none 不再支持。
  • baseUrl 不再支持,paths 需要相对于项目根目录。
  • types 默认值改为 []。依赖全局类型声明(如 @types/node)的项目需要显式列出。
  • rootDir 默认值改为 ./,内部源码目录需要显式设置。

其中 rootDirtypes 的变更最容易在升级时被忽略。如果你的 tsconfig.json 放在项目根目录而源码在 src/ 目录下,需要加上 "rootDir": "./src"。涉及 @types/node@types/jest 等全局类型的项目,需要显式添加到 types 数组。

此外,模板字面量类型对 Unicode 的处理方式发生了变化。之前的 UTF-16 索引行为会在处理 emoji 等补充平面字符时产生「半个字符」的代理对类型(\ud83d\ude00)。TS7 改成了按 Unicode 码点拆分,与 for...of[...str] 的行为一致。对依赖 UTF-16 级别字符串操作的类型工具来说,这是一个语义变化,不过在实际项目中很少会碰到。

—watch 模式重写,借力 Parcel 的文件监听

TS7 的 --watch 模式也完全重写了。旧版依赖操作系统的文件系统事件 API,跨平台一致性和稳定性都有不少坑。TS7 选择了将 Parcel 打包器的 @parcel/watcher 从 C++ 移植到 Go。

这个移植不是一个简单的跨语言翻译。团队先做了直接的 C++ → Go 逐行翻译,然后逐步重构成符合 Go 习惯的代码。最终产物是一个自包含的 Go 包,不需要 C++ 工具链依赖,同时通过了原版的测试套件。公告特别感谢了 Parcel 的作者 Devon Govett,因为 VS Code 多年来一直依赖 @parcel/watcher,这次移植也让 TypeScript 自己吃到了同一份红利。

业界反馈:从「几乎不可用」到「令人惊叹」

公告里引用了多个大型团队的反馈,这些数字比基准测试更有说服力:

  • Slack:合并队列时间减少 40%,CI 类型检查从 7.5 分钟降到 1.25 分钟。本地编辑器体验此前被描述为「几乎不可用」,工程师普遍让 CI 做全量类型检查。TS7 之后,同一套代码库在几秒内就能加载完毕。
  • Microsoft News Services:每月节省 400 小时的 CI 等待时间。
  • PowerBI:团队在 TS7 还不支持重命名功能时就已经将其设为默认编辑器体验,称其为「life-saving」。
  • Loop(微软协作工具):monorepo 级别下旧编辑器体验被描述为「不可用」,TS7 体验是「amazing」。
  • Canva:语言服务的首次错误显示时间从 58 秒降到 4.8 秒。
  • Vanta:最大项目上看到 9 倍的构建加速。

这些反馈指向同一个问题:开发循环被破坏——编辑器反馈延迟长到工程师宁愿让 CI 去跑类型检查,本地只做编辑。TS7 把反馈循环重新拉回秒级,这是它最核心的价值。

社区反应:速度红利和 API 缺口的拉锯

HN 讨论中(636 分,250 条评论),最受关注的话题有三个。

第一,与 Bun 的 Rust 迁移对比。Bun 最近宣布从 Zig 迁移到 Rust,采用了 AI 辅助的大规模一次性重写策略。TS7 的迁移则是一年多的渐进式工程,保持了与原代码库的结构对应。社区普遍认为 TS7 的路线更加审慎——一位用户评论道:「TS 的迁移在 AI 能帮忙之前就开始了,它完成得很慢、很小心,就像一个服务着几百万用户的项目应该做的那样。」这种对比本身不一定公平(两个项目规模和约束完全不同),但反映了社区对「编译器重写」这件事的敏感度。

第二,API 的缺失。对于 TS7 不提供 API 这件事,反应分两派。一派认为这是务实的选择:先把最核心的编译和语言服务交付出去,API 后续补上,总好过为了 API 的完整性再推迟半年。另一派则认为,这让整个依赖链上的工具(typescript-eslint、框架语言服务等)在短期内处于分裂状态——「升级了 TS7,lint 却跑在 TS6 上」的体验不够干净。

第三,对嵌入式框架的影响。HN 上有人专门引用了公告中关于 Vue、Svelte、Astro 等框架暂时无法使用 TS7 的段落。这对 Next.js、Nuxt、SvelteKit 等元框架的用户来说是一个不小的降级风险——如果项目同时使用这些框架,升级 TS7 可能意味着编辑器体验的退化而不是提升。Angular 用户相对幸运,至少可以走 CLI+TS7、编辑器+TS6 的并行路线。

Lobsters 上的讨论(73 分,21 条评论)则更侧重技术细节,包括 --checkers 参数的实际效果、新 watcher 在不同平台上的表现,以及 @typescript/native-preview 包(此前下载量已超过 850 万每周)到正式版的过渡。

什么时候升级

如果项目满足以下条件,TS7.0 现在就可以上:

  • 已经升级到 TS6.0 并通过所有检查
  • 不依赖 typescript-eslint 或其他直接 import typescript 的工具(或愿意用双编译器策略绕过)
  • 不使用 Vue、Svelte、Astro、MDX 等嵌入式 TypeScript 框架
  • CI 环境内存和 CPU 充足,可以尝试 --checkers--builders 调优

如果项目还在 TS5.x,建议先升级到 TS6.0,处理完所有 deprecation 警告后(特别是 rootDirtypes 的变更),再迁移到 TS7。

长期来看,TypeScript 7 的意义不只是「快」。它标志着 TypeScript 从一个自举的 JavaScript 编译器,变成了一个可以充分利用多核 CPU 的原生工具。这个架构选择为未来 5-10 年的 TypeScript 性能演进留出了空间。

本文的素材来自公开信息和社区讨论。如果你对这个话题有更深入的一手经验,欢迎指出文中的不足。

参考链接