TypeScript 7.0 Beta 发布:编译器重写为 Go,性能大幅提升
这次更新真正的大动作只用一句话就能说清楚:编译器被重写成 Go 了。
正因为这个变化,许多项目的构建速度会明显提升,而且 TypeScript 终于开始支持原生多线程。换句话说,这不是一次普通的版本更新,而是 TypeScript 底层发动机被换掉了。
下面直接拆开看:它新在哪里,哪些行为变了,以及你今天怎么开始试用。
如果你想实时跟进 React、JavaScript、TypeScript 以及更多前端技术动态,也可以订阅我们的 Telegram 频道,我们会持续更新最新内容和有意思的技术资讯。
新地基:Go 驱动的编译器
过去,TypeScript 一直是“自己编译自己”。也就是说,TypeScript 的代码库本身用 TypeScript 写,再编译成 JavaScript 运行。这种模式通常被称为 bootstrapped codebase。
但到了 7.0,这件事彻底变了。TypeScript 团队花了一年多时间,把现有代码库系统性地迁移到了 Go。这个工程量不小,但回报也非常直接:性能提升相当明显。
别被“Beta”这个标签吓到。对大多数使用场景来说,它已经足够接近生产可用。核心类型检查逻辑在结构上和 6.0 保持一致。也就是说,你不是在赌一套全新的语义,也不是在试一个未经验证的实验性行为。
TypeScript 7.0 已经跑过十年积累下来的测试,并且已经在 Bloomberg、Figma、Google、Slack、Vercel、Notion 等公司的数百万行代码库上使用过。
安装 Beta 很简单:
npm install -D @typescript/native-preview@beta然后用 tsgo 替代 tsc:
npx tsgo --version
# Version 7.0.0-beta对 VS Code 用户来说,TypeScript Native Preview 扩展可以把同样的性能提升带进编辑器里。自动导入、inlay hints、code lenses、跳转到源码定义等功能,也都能享受到这套新底座带来的速度提升。
并行化:终于吃满多核了
TypeScript 7.0 最大的架构收益之一,是很多编译步骤现在可以并行执行。
解析、类型检查、代码输出,都可以跨文件并发进行。代码库越大,这种收益越明显。以前 TypeScript 编译像是在一条窄路上排队通过,现在它终于开始利用多核 CPU,把任务分发出去。
类型检查也能并行
类型检查是最难并行化的部分。原因很简单:不同文件之间会共享类型信息,而且还必须在一致的顺序中完成检查。稍微处理不好,就可能出现不稳定、不一致,甚至难以复现的问题。
TypeScript 7.0 的做法是启动一个固定数量的 type-checker worker 池。每个 worker 都有自己对程序的视图,然后协作完成检查。默认情况下,它会使用 4 个 checker worker。
你也可以用新的 --checkers 参数调整数量:
npx tsgo --checkers 8 # 适合大型代码库
npx tsgo --checkers 2 # 更适合资源有限的 CI 环境worker 越多,构建可能越快,但内存占用也会随之上升。所以这里不是越大越好,而是要根据机器配置和项目规模找到平衡。
项目引用构建也能并行
TypeScript 7.0 现在还可以通过新的 --builders 参数,同时构建多个项目。对 monorepo 来说,这个变化非常关键。
npx tsgo --checkers 4 --builders 4不过要注意一点:--checkers 和 --builders 是会相乘的。比如上面这个配置,最多可能同时跑 16 个 type-checker。因此,在性能和资源之间找到合适比例,比盲目拉满更重要。
需要单线程?也可以
有些场景下,你可能并不想要并行。比如调试、性能对比,或者在资源非常有限的环境中运行。这时可以使用:
npx tsgo --singleThreaded它会把 type-checker 限制为 1 个,并强制解析和输出也在单线程中完成。这不是给日常开发准备的最快模式,但对排查问题很有用。
7.0 和 6.0 可以并排跑
未来,稳定版 TypeScript 7.0 最终会替换 typescript 包,并继续使用 tsc 作为入口。但在迁移阶段,为了降低切换成本,团队提供了一个兼容方案:
npm install -D typescript@npm:@typescript/typescript6也可以在 package.json 里这样写:
{
"devDependencies": {
"typescript": "npm:@typescript/typescript6@^6.0.0"
}
}这样一来,像 typescript-eslint 这种通过 peer dependency 引入 typescript 的工具,仍然可以访问 6.0 语义;与此同时,你可以在项目里并行试用 7.0。这对大型项目迁移非常重要。因为真正痛苦的不是安装新版本,而是生态工具链一起跟着变。
破坏性变化和配置更新
TypeScript 7.0 继承了 6.0 的新默认行为,并且把 6.0 中已经废弃的配置升级成硬错误。如果你还没有迁移到 6.0,现在最好先做这一步。这样会让 7.0 的迁移顺滑很多。
这里最关键的一点是:如果你的项目在 TypeScript 6.0 下可以干净编译,并且启用了 stableTypeOrdering,同时没有设置 ignoreDeprecations,那么它在 TypeScript 7.0 下应该会产出一致结果。
换句话说,如果你的 6.0 构建已经“干净且诚实”,没有靠废弃选项偷偷绕过去,那你距离 7.0 已经不远了。TypeScript 团队也强烈建议先采用 6.0 作为过渡台阶。很多项目仍然需要先消化 6.0 的新行为,再直接跳到 7.0。
默认设置变了
TypeScript 7.0 中,一批默认配置发生了变化:
strict: true
module: esnext
target: 当前稳定 ECMAScript,也就是 es2025
noUncheckedSideEffectImports: true
libReplacement: false
stableTypeOrdering: true,并且永久启用,不能关闭
rootDir: ./
types: []
最容易让你踩坑的,大概率是 rootDir 和 types。如果 rootDir 出问题,可以显式指定:
{
"compilerOptions": {
"rootDir": "./src"
},
"include": ["./src"]
}如果 types 出问题,也需要明确列出你真正需要的类型:
{
"compilerOptions": {
"types": ["node", "jest"]
}
}这类变化看起来不大,但在老项目里很可能会一下子暴露很多隐性依赖。
这些选项彻底没了
下面这些配置在 6.0 中已经被废弃,到了 7.0 会直接变成硬错误:
target: es5。你应该使用更现代的 target,或者交给单独的转译工具处理。
--downlevelIteration。它主要服务于 ES5,现在已经不再适用。
--moduleResolution node/node10。应该迁移到 nodenext 或 bundler。
--module amd | umd | systemjs | none。建议迁移到 esnext,再配合 bundler 使用。
--baseUrl。需要把 paths 更新为相对于项目根目录的路径。
--moduleResolution classic。应该使用 nodenext 或 bundler。
esModuleInterop: false 和 allowSyntheticDefaultImports: false。现在不再允许关闭。
alwaysStrict: false。所有代码都会以 strict mode 处理。
namespace 声明里的 module 关键字。应该改用 namespace。
imports 上的 asserts 关键字。应该改用 with。
outFile。应该交给 bundler 处理。
这不是 TypeScript 突然变得激进,而是在清理长期历史包袱。只是对老项目来说,这一步确实会有疼痛感。
JavaScript 文件支持被重做了
TypeScript 7.0 重新审视了 .js 文件的分析方式。目标很明确:让 JavaScript 文件的行为更接近 TypeScript 文件。
早期的 JavaScript 支持,主要围绕 JSDoc 注释和模式识别建立。当时它参考了 Closure 和 JSDoc 工具链里开发者正在使用的写法。这个设计很务实,也确实帮助了很多松散类型的 JS 代码库。但多年下来,它积累了大量特殊情况,并且和 .ts 文件的分析逻辑越来越不一致。
这次迁移到 Go,正好给团队提供了一个清理技术债的机会。于是,JS 和 TS 的分析管线开始被重新对齐。
需要注意的变化包括:
在需要类型的位置使用值时,要改成 typeof someValue。
@enum 被移除,应该改用 @typedef on (typeof YourEnum)[keyof typeof YourEnum]。
单独的 ? 类型不再保留特殊含义,应该使用 any。
函数上的 @class 不再推荐,应该改成真正的 class 声明。
后缀 ! 不再需要,直接使用 T。
紧挨着标识符的 @typedef 不再被接受,必须写在 tag 本身内部。
Closure 风格的函数类型语法,比如:
function(string): void应该改成:
(s: string) => void此外,一些模式也不再享受特殊处理,比如给 this 起别名,或者重新赋值整个函数的 prototype。
简单说,TypeScript 7.0 对 JavaScript 文件更严格,也更一致。它不再愿意背那么多历史兼容包袱。
编辑器体验也变快了
7.0 的性能提升,并不只体现在命令行里。VS Code 的 TypeScript Native Preview 扩展已经逐渐成熟,现在支持:
自动导入
可展开的 hover 提示
inlay hints
code lenses
跳转到源码定义
JSX linked editing 和标签补全
它基于 Language Server Protocol 构建,因此不只服务于 VS Code,也可以在多数编辑器中工作。同时,它会继续使用你现有的 tsconfig 设置,把 CLI 里的性能提升带进日常编辑体验。
当然,还有一些功能仍在追赶中。但它已经足够快、足够稳定,也已经可以支撑很多日常 TypeScript 开发工作。
最后
TypeScript 7.0 Beta 最重要的地方,不是多了几个漂亮的新语法。它真正改变的是底座。
编译器从 TypeScript/JavaScript 迁移到 Go,意味着 TypeScript 开始真正拥抱原生性能、多线程和更现代的工程架构。对小项目来说,你可能只是觉得“快了一点”。但对大型代码库、monorepo、CI 构建和编辑器响应来说,这会是非常实际的变化。
当然,代价也很明确。老配置会被清理,历史行为会被收紧,JavaScript 文件分析会更一致也更严格。那些长期靠旧选项和隐式行为维持的项目,迁移时大概率会被迫面对技术债。
但这未必是坏事。TypeScript 7.0 像是在说:过去十几年积累下来的包袱,该还的终于要还了。
如果你的项目已经在 TypeScript 6.0 下干净运行,那么试用 7.0 的门槛并不高。先安装 @typescript/native-preview@beta,用 tsgo 跑一遍,再看看构建速度和编辑器体验的变化。
本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!