TypeScript 7与Go Port:更快的构建速度、内存优化以及编辑器实时反馈功能。
TypeScript 7将编译器替换为原生Go引擎,可实现并行构建、降低内存占用,同时配备新的语言服务器,此外还有需要先了解的迁移注意事项。
来源: TypeScript 7 Is Here — And It Changes Much More Than the Compiler
任何使用过多年 TypeScript 的人都熟悉这样的工作流程:先编写代码,编辑器会对代码进行分析,TypeScript 会处理整个项目,之后再运行 tsc,接着又得等待。在大型单仓库项目中,这些等待时间甚至长到足以去喝杯咖啡。但这并不意味着该工具的设计有缺陷。它的类型系统与语言工具已经足够强大,能够处理极其庞大的代码库,这也正是它成为 JavaScript 生态中核心工具的原因。然而,这种强大也带来了代价:随着项目规模的扩大,编译器和语言服务器逐渐变成了性能瓶颈。
TypeScript 7.0 是微软的回应,值得注意的是,其主要变化并非新的运算符、关键字或语法特性,而是底层的编译引擎。以往 TypeScript 的编译器是用 TypeScript 自身编写的,这种递归式的设计虽然运行良好,但也意味着编译器必须依赖 JavaScript 的运行时模型。在 7 版中,微软将编译器移植到了 Go 语言上,从而实现了能够充分利用现代硬件与并行处理能力的原生实现。
这就是这一版本的核心要点:TypeScript 7 并不是一种全新的语言,而是为人们已使用的那种语言提供的新引擎,这样的定位几乎可以解释它的一切特性。
速度数据
总体性能提升了十倍。微软的测试结果显示,根据项目不同,完整构建的运行速度通常可提高8到12倍,而这些测试数据来自真实的庞大代码库,而非人工设计的微型基准测试。
构建时间甚至还不是最令人瞩目的成果,因为语言服务器的速度也有所提升。在微软使用VS Code代码库进行的测试中,打开包含错误的文件,从错误出现前的大约17.5秒缩短到了1.3秒不到。这带来了截然不同的使用体验,在大型代码库中,这种提升比仅仅减少几百毫秒的构建时间更为重要。
充分利用每一核心
现代机器拥有众多核心,而传统的 tsc 只能使用一个核心。TypeScript 7 能更高效地利用这些核心:在可能的情况下,解析、类型检查及代码生成可以并行执行。此外它还添加了一些实验性的开关选项:
--checkers
--builders
--singleThreaded
前两种方式能更精细地控制并行任务的分配方式,而 --singleThreaded 则可在需要时关闭并行处理,例如在调试编译器行为或在资源受限的环境中运行时。
单仓库架构能从中获得最大益处。想象一个包含 apps 目录的仓库:
apps/
web/
admin/
mobile/
以及一个包目录:
packages/
ui/
api/
config/
utils/
domain/
TypeScript过去需要在那个依赖关系图中执行大量顺序操作。到了7版本后,更多操作可以同时进行。因此,其优势并不仅在于编译器速度更快,还在于编译器终于能够充分利用运行它的硬件资源。
内存
性能并不仅取决于CPU使用时间。大型TypeScript项目会占用数GB的RAM,尤其是当语言服务器与编辑器、浏览器、Docker以及开发服务器同时运行时。微软公布的测试数据显示,多个大型项目的内存占用减少了6%到26%:
- Bluesky:减少了约26%
- VS Code:减少了约18%
- tldraw:减少了约15%
- Playwright:减少了约11%
虽然相比之前的十倍速构建提升看似微不足道,但任何经历过大型单体仓库导致笔记本电脑内存耗尽的人都能理解这一优势的价值。
新的语言服务器
TypeScript的吸引力其实大多并非来自tsc,而是源自编辑器功能:自动补全、悬停显示类型信息、跳转至定义位置、列出所有引用、全局重命名符号、内联显示错误并支持一键修复。现代JavaScript开发的诸多便利都依赖于这些功能。
TypeScript 7带来了基于语言服务器协议构建的新语言服务器,采用了原生实现和多线程技术。开发团队持续完善其功能:代码透镜、内嵌提示、语义高亮、导入项排序及移除未使用导入等功能已经加入,同时还具备了自动导入、跳转至源代码定义、JSX关联编辑以及标签补全等功能。其目标不仅仅是让tsc运行更快,而是让从输入代码到获得反馈的整个流程都更加迅速,这或许才是更大的优势。
并行环境下的确定性输出
有一个变化虽然不那么引人注目,但在技术上却相当巧妙。TypeScript 通过类型、符号、联合类型以及声明等机制进行大量内部处理。当多个工作线程同时运行时,内部对象的创建顺序可能会发生变化,这会导致内部标识符改变,进而影响生成的声明顺序。
TypeScript 7 通过根据内部对象的内容以确定性方式排序来解决这个问题,而非依赖对象被访问的顺序。以这个函数为例:
function foo(condition: boolean) {
return condition ? 100 : 500;
}
它能够生成如下这样的声明:
export declare function foo(
condition: boolean
): 100 | 500;
无论并行任务如何执行,并集的排序都会保持稳定。大多数开发者可能不会注意到这一点,但这正是让高度并行的编译器具备可靠性的技术保障。
并非功能版本发布
那些期待类似功能的人:
type NewSuperPower<T> = ...
或者,由于新增了大量语言特性,初看之下TypeScript 7可能会让人觉得不够惊艳。大部分精力都投入到了基础设施建设上,而非新的类型系统功能上。团队花费数年时间为下一代TypeScript打基础,如今它终于问世了。路线图指出,在7.0版本之后,将进一步开发新特性、优化用户体验、提升性能,并推出新的编译器API。这一版本更像是新时代的开端,而非旧时代的终结。
工具开发者的注意事项
对于那些开发工具的人来说,这里的情况就变得有趣了。TypeScript 7.0并未附带旧的编译器API,团队预计7.1版本将会引入新的API。这非常重要,因为生态系统中的许多工具并不仅仅运行tsc命令,代码检查工具、框架编译器、语言服务以及构建工具都会以编程方式与TypeScript交互。
这也是为什么 TypeScript 6 和 7 目前可能需要共存的原因之一。微软推出了 @typescript/typescript6 以简化过渡过程,这样项目就可以在继续使用需要其 API 的工具的同时,单独使用版本 7 的编译器。编译器的升级并不总像修改一行代码那么简单:
{
"devDependencies": {
"typescript": "^7.0.0"
}
}
在大型生态系统中,编译器属于基础设施,而基础设施本身存在各种依赖关系。
另一个限制体现在那些将 TypeScript 整合到自身编译或语言服务流程中的框架和工具上。Vue、MDX、Astro、Svelte 和 Angular 的开发流程仍处于对新语言服务设计的支持跟进阶段,缺乏稳定的编程 API 正是造成这一状况的原因。普通的 React 加 TypeScript 应用可以较为轻松地完成迁移,而复杂的框架集成、编译器插件或语言服务插件则面临更大的挑战。在升级任何大型生产代码库之前,值得先进行相关检查。
TypeScript 6 作为过渡桥梁
TypeScript 6绝非仅仅是7版本之前的一个发布版本,它被刻意设计成一座桥梁。当时已有若干旧编译器选项被标记为过时,而在7版本中则完全被移除,因此团队建议在升级之前先清理这些选项。如下所示,通过中间版本进行过渡,比直接将7视为独立升级更为稳妥:
TypeScript 5.x
↓
TypeScript 6
↓
TypeScript 7
在 TypeScript 6 中,项目产生的任何弃用警告都值得重视。它们实际上是从未来发来的迁移通知。
为何反馈循环如此重要
TypeScript 在编译后会消失,因此前端开发者很少将其视为应用程序运行时的一部分。但它实际上对开发运行时有着深远影响。每当编辑器经历这样的循环时:
type something
↓
autocomplete appears
↓
you navigate to a definition
↓
you rename a symbol
↓
you save
↓
CI runs
↓
the project gets type-checked
TypeScript 每次都会参与其中,且随着应用程序的发展,它的作用也越来越重要。100 毫秒的延迟无关紧要,但 10 秒的延迟就很显著;30 秒的等待会改变一个人的工作方式,而五分钟的 CI 类型检查则会影响整个团队的工作方式。因此,TypeScript 7 的主要优势并非编译速度提升十倍,而是缩短了编写代码与确认其正确性之间的时间间隔。
尝试使用
对于新项目,显然值得考虑使用 TypeScript 7。而对于现有项目,则应采取更为谨慎的态度。首先将其作为开发依赖项进行安装:
npm install -D typescript@7
然后运行类型检查,但不要输出任何内容:
npx tsc --noEmit
检查结果时,请关注以下方面:
- 编译器错误
- 已废弃的配置
- 构建工具的兼容性
- ESLint集成情况
- 框架集成情况
- IDE的运行表现
- 持续集成流程的性能
- 内存占用情况
在大型单仓库项目中,应使用类似工具来对比实施前后的性能:
time npx tsc --build
并将输出结果与当前的 TypeScript 版本进行对比。不应只关注最终数值,整个开发者体验才是关键。
重建基础
TypeScript 7 在前端工具领域表现突出,因为其团队没有选择在现有架构上添加更多功能,而是重新构建了基础框架。这种语言本身无需重新设计,但基础设施需要。选择此时推出也很合理——随着 JavaScript 项目规模变大、单仓库架构越来越普遍、类型安全的 API 无处不在、编辑器功能日益智能、AI 编码工具对语义数据的需求不断增长,同时开发者也期望能获得近乎即时的响应。2015 年时还能满足应用需求的编译器,未必能跟上 2026 年单仓库架构的发展速度。
简而言之,这次发布承认旧设计虽然有效,但已无法满足现代软件的需求。团队没有放弃开发者已熟悉的类型系统,而是重新构建了其底层机制。正因如此,这次发布的意义远超其表面上的功能列表所示。它既是 TypeScript 未来发展的基础,也能提升 tsc 的运行速度。如果这些预期优势能惠及整个生态系统,最令人期待的 TypeScript 新功能甚至可能不会出现在 7 版中——因为正是 7 版足够快速,才使得这些功能得以实现。
“十倍提升”是标题所强调的点,但其背后其实还包括并行处理、原生执行、更低的内存占用、全新的语言服务器、确定的编译器输出,以及为后续工具开发打下的基础。对于那些需要维护大型 TypeScript 应用的人来说,这些价值显然远超过另一款类型工具。