摘要:事情起因于 3 月 11 日,微软在官方博客上宣布了一则重大消息:TypeScript 编译器和工具链将迎来原生实现。简单来看,所谓原生实现,就是用一种更接近计算机底层的语言(如 Rust、Go 或 C++)重新实现 TypeScript 编译器和相关工具,而
整理 | 屠敏
出品 | CSDN(ID:CSDNnews)
这一次,由微软牵头,又掀起了一场关于编程语言的大战。
事情起因于 3 月 11 日,微软在官方博客上宣布了一则重大消息:TypeScript 编译器和工具链将迎来原生实现。简单来看,所谓原生实现,就是用一种更接近计算机底层的语言(如 Rust、Go 或 C++)重新实现 TypeScript 编译器和相关工具,而不是继续使用 JavaScript/TypeScript 本身来编写它们。
但有些出乎众人意料的是,微软此次并没有选择自家设计的 C# 语言,也没有使用之前大家都看好的 Rust,而是转向了 Google 开发的 Go。甚至在初步移植后,微软大赞,原生版本的 TypeScript 编译器性能提升了 10 倍。
更值得一提的是,这次的移植工作由 C#、TypeScript 之父 Anders Hejlsberg 亲自操刀。
为什么要开发原生的 TypeScript 编译器、工具链?
据悉,基于 Go 语言的 TypeScript 编译器和工具的项目代号为“Corsa”。之所以要将其移植,Anders Hejlsberg 也在博文中给出了详尽的理由。
Anders Hejlsberg 称,TypeScript 最大的价值就是让开发体验更顺滑,项目代码越多,TypeScript 的优势就越明显。
不过,当代码规模大到一定程度,TypeScript 反而会开始拖后腿。
在日常开发工作中,想必不少开发者也有这样的体验,打开一个大型项目时经常会遇到编辑器启动慢、代码检查时间长的问题。大家都希望可以快速定位函数、安心地重命名变量、流畅的浏览代码,但现实情况是:TypeScript 在超大代码库下响应越来越慢,影响开发效率。
正如 Anders Hejlsberg 所说:“我们可能已经达到了 JavaScript 所能发挥的极限。”
尤其是 AI 辅助编程工具(比如 GitHub Copilot)需要快速读取大量代码信息,TypeScript 现有的性能已经不太够用了。另外,开发者也希望命令行构建速度更快,能迅速检查整个项目是否正常。
为了解决这些问题,在 Anders Hejlsberg 主导下,TypeScript 团队决定开发原生版本的编译器和工具。在官方团队看来,原生实现可以:
更快地启动编辑器,告别长时间的“加载中”;
将大多数编译速度提升 10 倍,大幅缩短构建时间;
降低内存占用,让开发环境更流畅。
原生编译带来的 10 倍速度提升
根据微软透露,TypeScript 团队已经着手开发 TypeScript 编译器和工具的原生移植到 Go,通过从原始代码库直接、逐个文件和逐个函数的转换。
当前,其原生实现已经能够加载许多流行的 TypeScript 项目,包括 TypeScript 编译器本身。
虽然目前这一项目刚刚起步,但是也能看到不错的效果。这里是 tsc(TypeScript 编译器)在 GitHub 上几个不同规模流行代码库上的运行时间:
项目代码行数 (LOC)现有 TypeScript (JS)原生 TypeScript提速 VS Code1,505,00077.8s7.5s10.4xPlaywright356,00011.1s1.1s10.1xTypeORM270,00017.5s1.3s13.5xdate-fns104,0006.5s0.7s9.5xtRPC (server + client)18,0005.5s0.6s9.1xrxjs (observable)2,1001.1s0.1s11.0x正如上面表格显示,编译 Visual Studio Code 的 150 万行代码从原来的 77.8 秒直接缩短至 7.5 秒。
Anders Hejlsberg 表示,“虽然我们的功能还不完全齐全,但这些数字足以表明你在检查大多数代码库时能看到性能上有一个数量级的提升。我们对这种速度大幅提升所带来的机会感到非常兴奋。以前觉得遥不可及的一些功能现在变得触手可及了。这次原生移植将为整个项目提供即时、全面的错误列表,支持更高级的重构,并开启之前计算成本太高的更深层次的洞察。”
编辑器响应更快,内存占用更低
除此之外,使用 Go 改写后的 TypeScript 编译器以及工具链还将大幅提升代码编辑器的使用体验。
以 Visual Studio Code 代码库为基准,在一台性能不错的计算机上加载整个 VS Code 代码库目前需要约 9.6 秒,而使用原生语言服务,仅需 1.2 秒。在编辑器场景下,项目加载时间提升了 8 倍。
与此同时,官方初步测试显示内存占用减少约 50%,进一步优化了开发流畅度。
TypeScript 的后续版本
随着 TypeScript 工具链用 Go 语言改写,TypeScript 语言自身版本的迭代也迎来了一些改变。
当前 TypeScript 最新发布的版本是 TypeScript 5.8,5.9 也即将推出。微软表示,基于 JavaScript 的代码库仍会继续迭代,进入 TypeScript 6.x 版本系列。其中,TypeScript 6.0 将引入一些弃用和不兼容的变更,为未来的原生版本做准备。
当原生代码库的功能和现有 TypeScript 足够接近时,微软透露,就会正式发布 TypeScript 7.0 版本,目前这部分仍在开发中。
为了方便区分,未来微软会使用以下命名方式:
TypeScript 6(JS) —— 继续基于 JavaScript 代码库的版本
TypeScript 7(Native) —— 原生实现的全新版本
部分项目在 TypeScript 7 发布后可以直接迁移到原生版本。微软表示,某些项目可能依赖特定 API、旧配置或其他约束,短期内仍需继续使用 TypeScript 6。考虑到 TypeScript 在 JavaScript 生态中的核心地位,微软承诺将继续维护 TypeScript 6.x,直到 TypeScript 7+ 足够稳定并得到广泛采用。
长期目标是确保两个版本的兼容性,允许开发者根据需求灵活升级到 TypeScript 7,或在必要时回退至 TypeScript 6。
编程语言之争:为什么没用 Rust、C#?
当前 TypeScript 原生编译的迁移将分阶段进行。微软预计将在 2025 年中期预览 TypeScript 编译器的本机实现,该编译器能够进行命令行类型检查。到了 2025 年底,完整支持项目构建和编辑器的 TypeScript 语言服务。
目前,TypeScript 团队已经把初期的代码托管在 GitHub(https://github.com/microsoft/typescript-go),使用的是 Go 语言实现,并遵循原有的开源协议。开发者可以自行编译和运行这个新版本的 tsc,具体步骤可以参考 README 文件。随着新功能的完善,官方也将定期更新进展。
此次原生迁移不仅提升了 TypeScript 的开发体验,还为 AI 驱动的编程工具奠定了基础,使未来的自动化编程和智能化开发变得更加可行。
不过,微软的这一举措也引发了广泛的讨论,甚至多个话题登上了 HN 的热榜,引发了一场关于编程语言的激烈辩论。
一些开发者质疑,微软为何选择了 Go 语言,而不是自家设计的 C# 或各大公司推崇的 Rust。
对此,TypeScript 团队也提前预料到了业界网友会有这一层面的疑问,并且已经在 GitHub Discussions 上写了一篇 FAQ 来解答:
关于为什么选择 Go,微软 TypeScript 团队的开发主管 RyanCavanaugh 写道:“编程语言的选择总是一个热门话题!我们对多种语言进行了深入评估,不仅包括近期的调研,也结合了之前的研究。我们甚至考虑过混合方案,比如用原生语言实现某些组件,而核心的类型检查算法仍然使用 JavaScript。为了验证不同语言的可行性,我们编写了多个原型,测试不同的数据表示方式,并深入研究了已有的原生 TypeScript 解析器(如 swc、oxc 和 esbuild)所采用的方法。”
那要问为什么最终选择 Go,RyanCavanaugh 称,最重要的考虑因素是尽可能保持新代码库的兼容性,无论是在语义层面,还是在代码结构上。「因为我们预计在相当长的一段时间内都会同时维护 JavaScript 和 Go 这两个代码库,因此,我们需要一种可以让代码在两者之间轻松迁移的语言。而如果选择那些需要彻底改变内存管理、数据结构、惰性计算等核心机制的语言,可能更适合从零开始重写,但不适合这种以迁移为主的改造。」
RyanCavanaugh 补充说道:
「Go 语言的编码风格与 TypeScript 现有代码库的模式高度相似,使得迁移工作更加可行。此外,Go 允许精细控制内存布局和分配(可以针对对象和字段进行优化),但又不需要开发者在整个代码库中时刻操心内存管理问题。虽然 Go 使用了垃圾回收(GC),但这对 TypeScript 编译器来说并不会造成显著影响——因为:
1.批量编译(Batch Compilation)模式下,GC 影响极小:整个进程在编译完成后就会终止,垃圾回收的代价几乎可以忽略。
2.非批量场景(如语言服务)下,内存占用模式非常稳定:大多数内存分配(如 AST 语法树)会贯穿程序整个生命周期,我们可以利用这一特点,在逻辑合适的时间触发 GC,避免不必要的性能开销。
此外,TypeScript 编译器涉及大量的图处理和树遍历,需要在不同层级的节点间进行双向访问,并处理多态结构。Go 在这方面的处理非常直观,特别是在希望保持与 JavaScript 版本代码结构相似的情况下,Go 让实现变得更加自然。」
不过,Go 也有一些短板,比如在 JavaScript 生态中的原生交互能力不如某些其他语言。微软表示,“但我们已经制定了计划来优化这部分体验,并承诺会提供一个高性能、易用的 JS API。事实上,我们当前的 API 设计使得使用者几乎可以随意访问甚至修改内部数据结构,这在一定程度上限制了优化空间。而通过新的 API 设计,我们不仅可以提高性能,还能确保未来的代码架构更灵活,同时减少对 API 兼容性的顾虑。”
总的来说,Go 语言在代码可迁移性、内存管理、性能优化、类型检查实现等多个方面都满足了 TypeScript 迁移的需求,因此成为了最终的选择。
不过,对于 RyanCavanaugh 的解释,也依然有不少开发者并不买账。一位资深首席架构师 EisenbergEffect 评价道:
我希望能看到一篇更深入的技术决策分析。
微软自家拥有 C#,而 C# 又是 Go 的直接竞争对手。因此,选择 Go 令人颇感意外。更何况,微软有大量同时使用 TypeScript 和 C# 的客户。这似乎是一个错失的机会——微软本可以借此整合其 Web 开发生态,打造更强大的方案。
事实上,这甚至有些像是对 C# 的不信任投票。毕竟,Anders 是 C# 的原始作者,而他的团队如今却没有选择 C#。如果 C# 存在问题,或许更好的做法是与 C# 团队合作,改进 C#,使其成为新 TypeScript 编译器的最佳选择。我实在不确定该如何解读这一决定……
如果不选 C#,我原本会认为 Rust 才是更合理的选择,毕竟整个生态系统的趋势都在向 Rust 靠拢。这个决定同样出乎意料。
此外,C# 和 Rust 在 WASM 方面都有很强的支持,据我所知,它们的 WASM 兼容性比 Go 更好。而 TypeScript 编译器有相当一部分用户需要在浏览器中运行,不知道这个决策会如何影响这些场景。
我很高兴微软优先考虑了性能,但对具体的选择感到失望。
对此,你怎么看待微软拥抱 Go 而不选 Rust 亦或者 C# 这一举措?
参考:
https://news.ycombinator.com/item?id=43332830
来源:CSDN