tsrs 技术解析用 Rust 移植 TypeScript 7,类型检查还能怎样提速?

一、先把 tsrs 放回 TypeScript 工具链

理解 tsrs,首先要分清"编译器的实现语言"和"业务代码的输出语言"。

你仍然编写 TypeScript,仍然使用 tsconfig.json。Rust 描述的是 tsrs 本身的实现方式;业务代码按配置生成 JavaScript、声明文件和 source maps。只想检查类型时,使用 --noEmit。

这里有一个容易忽略的细节:增量模式下,--noEmit 仍可能更新 .tsbuildinfo,所以它不等于禁止写入所有文件。GitHub

图 1:输入、检查与输出的概念关系,并非编译器内部调用时序。

还需要更新一个容易过时的背景:TypeScript 7.0 已在 2026 年 7 月正式发布,官方编译器采用 Go 实现,常规命令仍是 tsc。 tsrs 文档中的 tsgo 通常指它对照的 Go 实现,不应把它与 TypeScript 7 当作两个毫无关系的产品。TypeScript

实现 主要实现语言 理解它与 tsrs 的关系
TypeScript 6 及以前的经典编译器 TypeScript / JavaScript 旧一代实现,迁移时还涉及上游版本变化
TypeScript 7 官方编译器 Go tsrs 跟踪的语言与编译器行为参照
tsrs Rust 针对固定 TypeScript 7 提交进行移植与优化

截至本文核验,tsrs 0.20.1 对应 TypeScript 7.1.0-beta,固定上游提交为 3e9236361fa9。包名中的两段版本各有含义:前半段是 tsrs 版本,后半段标明它跟踪的 TypeScript 版本。GitHub

二、移植一个编译器,难点首先在"行为一致"

TypeScript 类型检查需要处理跨文件符号、泛型实例化、条件类型、结构化类型关系和控制流收窄。对用户来说,检查器有价值的前提是:该发现的错误能够稳定发现,已有代码不会因为实现替换而产生难以解释的差异。

tsrs 的移植指南采用逐函数对照上游的路线,保留算法结构、调用关系和执行顺序。它的 scanner、parser、binder、checker 等模块与 Go 实现对应。

解析和绑定可以按文件并行;绑定完成后的部分前端数据共享只读,而各 checker 保存自己的类型、签名与关联状态。GitHub

这意味着,tsrs 的工程难题包含两部分:一方面保持上游行为,另一方面改进承载这些行为的数据结构和执行方式。换成 Rust 本身,并不能自动证明结果更快或者更加兼容。

兼容性也不止是"错误数量相同"。错误出现的位置、诊断码、文本、顺序和退出码,都可能影响编辑器、测试与 CI。项目在默认对照设置下,把这些相对固定上游的差异视为需要处理的问题;--fast 则另有明确边界。GitHub

因此,评估 tsrs 时要问的是:

它在我的代码、配置和目标 TypeScript 版本上,能否保持所需结果,并减少实际等待时间?

三、快在哪里:数据布局、并行调度与按需计算

1. 让编译器内部的数据更紧凑

编译器需要维护大量节点、符号和类型之间的关联。tsrs 将许多核心对象分配在 arena 中,并通过保留对象身份的 P<T> 句柄访问。在适用的 Unix 构建中,默认采用 32 位压缩句柄;相关文档也明确区分普通指针构建和历史实验。GitHub

从工程上理解,这类设计的价值在于减少对象关系的存储成本,并改善数据访问的局部性。它优化的是编译器工作时的数据表示,而业务侧的 TypeScript 语义仍由上游实现决定。

具体能节省多少内存,需要结合项目测量。

2. 默认模式已经包含优化

tsrs 并不是关闭 --fast 就完全没有优化。保持行为的控制流记忆化、并行解析,以及构建和数据布局层面的优化,在默认模式下也可以生效。GitHub

从 0.20.0 起,默认模式使用固定上游的 checker 设置,通常为 4 个 checker,且不超过文件数;--fast 才进一步启用自适应并行、局部性调度、额外缓存与惰性成员处理。--build 的 fast 模式仍按每项目 4 个 checker 执行。GitHub

图 2:以 0.20.1 文档为准。优化预设会保留项目中的检查选项,但并非对所有程序都保持诊断完全一致。

3. --fast 需要单独评估

惰性计算可以避免提前展开暂时用不到的类型信息;更多 checker 有机会提高并行度,也可能增加状态与缓存占用。这些方向之间存在取舍。

官方列出的边界包括:在某些检查顺序、递归类型和实例化限制场景中,fast 模式可能改变诊断内容、出现位置,甚至退出码。

它不会替你关闭 strict,但"配置没有变"不代表"所有边界行为都不变"。切换检查历史或惰性成员设置,还可能使不兼容的增量缓存失效。GitHub

对实际项目而言,合理的顺序是先检查默认模式的结果,再决定是否启用 fast。

四、官方基准:速度和内存要放在一起看

官方在 2026 年 10 月 27 日公布了一组发布二进制基准:TypeScript 7.1.0-beta,对比 tsrs 0.20.0-ts7.1.0-beta 的默认模式与 fast 模式。

本文从完整的 19 个场景中,选取 TypeScript 基线耗时最长的 3 个项目 展示。GitHub

图 3:按官方结果重绘,数值越低越好。RSS 表示进程驻留内存;图中为各次运行峰值 RSS 的中位数。

读这张图,至少要保留三个判断。

第一,对照组已经是原生 TypeScript 7.1 beta。 图中的收益发生在 Go 原生编译器这一基线上,不能将其误写为只与旧版 JavaScript 实现比较。

第二,fast 不一定比 tsrs 默认模式更省内存。 图中的 t3code-server 和 mikro-orm 都体现了这一取舍。选择模式时,时间和内存应该共同参与决策。

第三,这些收益只适用于所测工作负载。 本次使用 Apple M3 Max、14 核、36 GB 内存,关闭代码输出和增量编译,预热文件缓存后轮换运行。各组采用自己的默认并行配置,没有强制相同 checker 数量。GitHub

因此,这张图不能直接说明冷启动、增量重编译、编辑器补全或浏览器 Wasm 的性能,也不能据此宣称整个 CI 流水线会获得相同倍数的提升。官方对不同工作负载安排了不同的基准体系。GitHub

假设类型检查占一次 CI 总耗时的 40%,即便这一阶段缩短到原来的四分之一,整条流水线耗时也只是变为原来的:

60 % + 40 % 4 = 70 % 60\%+\frac{40\%}{4}=70\% 60%+440%=70%

也就是整体耗时减少 30%。这是一个计算示例,说明局部优化如何影响整体,并非 tsrs 的实测数据。

五、动手试用:先复现正确性,再比较性能

以下示例固定版本,便于复现:

bash 复制代码
npm install -D --save-exact tsrs@0.20.1-ts7.1.0-beta
npx --no-install tsrs --version

该版本对应官方发布说明中的 TypeScript 7.1 beta 移植版本。GitHub

准备一个 tsconfig.json:

json 复制代码
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "strict": true,
    "rootDir": "src",
    "outDir": "dist"
  },
  "include": ["src/**/*.ts"]
}

在 src/index.ts 中放入一个有意写错的赋值:

ts 复制代码
type User = {
  id: number;
  name: string;
};

export const user: User = {
  id: "1001",
  name: "Ada"
};

先运行默认模式,再单独运行 fast 模式:

bash 复制代码
# 显式关闭 fast,便于建立对照
npx --no-install tsrs -p . --noEmit --fast false

# 再评估 fast
npx --no-install tsrs -p . --noEmit --fast

这些选项的使用方式与官方 CLI 文档一致。GitHub

在本文的 Linux x64、Node.js 24.22.1 验证环境中,tsrs 两种模式与官方 TypeScript 7.1 beta 均报告 TS2322,退出码为 2。将 id 改成数值 1001 后,三者均通过检查,退出码为 0。

移除 --noEmit 后,也可以验证输出能力:

bash 复制代码
npx --no-install tsrs -p . --declaration --sourceMap

上述修正后的最小示例,其 JavaScript、声明文件和 source map 输出也与固定版本的官方编译器一致。

这只是该示例的实际验证结果,不代表完成了真实项目的兼容性认证。

接入已有项目时,可以先增加独立脚本:

json 复制代码
{
  "scripts": {
    "typecheck": "tsc -p tsconfig.json --noEmit",
    "typecheck:tsrs": "tsrs -p tsconfig.json --noEmit --fast false",
    "typecheck:tsrs:fast": "tsrs -p tsconfig.json --noEmit --fast"
  }
}

这段配置的作用,是让现有检查命令与试验命令能够分别运行。

做诊断对照时,应保持源码、依赖与配置一致,并检查退出码、文件位置、错误码和消息文本。还要清理可能影响结果的 TSRS_* 环境设置;--fast false 不会撤销显式配置的单项优化。GitHub

如果原项目仍使用 TypeScript 5 或 6,需要先区分"升级上游版本带来的变化"和"更换编译器实现带来的变化"。否则,一个本来由 TypeScript 7 引入的诊断变化,很容易被误判为 tsrs 的问题。

六、迁移前,确认四条能力边界

命令行:常用能力与辅助命令并不完全同步

tsrs 已覆盖类型检查、代码输出、增量编译和项目引用等主要流程,但当前仍不支持 --init、--showConfig。

平台支持也要看具体功能:Windows x64 有预编译包,Windows CLI watch 仍未支持,不能把"可以安装"理解为"每种运行模式都能用"。GitHub

编辑器:命令行接入与语言服务接入是两件事

语言服务器提供 LSP 入口:

bash 复制代码
tsrs --lsp -stdio

让终端中的检查脚本使用 tsrs,并不会自动切换编辑器的 TypeScript 服务。应按照对应编辑器与平台的官方设置说明接入,并验证补全、跳转、重命名和保存后的诊断体验。

当前语言服务器尚未移植 content mapper 执行和自动类型获取;CLI 中可用的 mapper 工作流,不能直接视为编辑器内也已支持。GitHub

Compiler API:要区分新 API 与旧对象模型

tsrs 提供 TypeScript 7 风格的 tsrs/sync、tsrs/async 和 AST 等入口。

不过,它不是旧版 typescript.createProgram() 对象模型的透明替代。依赖旧 Compiler API 的插件、文档生成器或代码分析工具,需要单独验证。GitHub

WebAssembly:扩展运行位置,也有自己的约束

@tsrs/wasm 面向 Node.js 22+ 和浏览器,使用同一套 Rust 编译器代码,目标为 wasm32-wasip1。它可以在浏览器内存文件系统中执行检查和输出,为在线编辑器、教学环境及本地化代码分析提供可能。

但当前 Wasm 版本运行在单线程模式,不能套用原生多线程基准。浏览器集成需要提供项目文件与依赖声明,官方建议自行创建 Web Worker,以免同步编译阻塞页面。

Wasm 包目前也不提供 --watch、--lsp 和 --api 服务器;单实例线性内存的理论上限为 4 GiB,实际可用上限还受运行时约束。GitHub

七、哪些项目值得先试?

基于上述设计与公开数据,最有理由尝试 tsrs 的,是已经测出类型检查耗时或内存占用明显,并且能够建立结果对照的项目。

一个可执行的评估过程是:

  1. 保存现状。 记录现有编译器版本、完整诊断、检查耗时和峰值内存,确认真正的瓶颈。
  2. 验证默认模式。 在相同输入下运行 tsrs,处理版本差异与诊断差异。
  3. 单独评估 fast。 重复测量,关注诊断变化、缓存条件,以及时间和内存的取舍。
  4. 逐步切换。 先在部分项目或非阻断作业中观察,再决定是否调整默认检查命令,并保留可恢复的原有配置。

对于代码量很小、类型检查占总耗时很低,或者高度依赖旧 Compiler API 的项目,迁移的优先级可能没有基准图呈现得那么高。这是基于集成成本与收益的工程判断,需要由项目自己的测量来决定。

tsrs 值得关注的地方,在于它尝试同时推进两件难事:持续跟随 TypeScript 的行为,以及通过更细致的数据布局、调度与缓存设计减少检查成本。

对使用者来说,成熟的采用标准也应同时包含这两项:结果满足要求,收益能够复现。

相关推荐
透明的玻璃杯1 小时前
VS2015+QT 多线程
开发语言·qt
码匠许师傅2 小时前
【C++三方组件】mbedTLS:面向嵌入式的轻量 TLS
开发语言·c++
迪菲赫尔曼2 小时前
【基础篇 12】把环境与源码接起来:检查 GPU,再安装服务器上的项目
运维·服务器·开发语言·人工智能·python·yolo·目标检测
2601_962885722 小时前
2026 Python 股票数据接口选型指南(横评 + 决策树)
开发语言·python·区块链
Evand J3 小时前
【PMSM例程4】PMSM电阻辨识与模型补偿EKF,MATLAB例程。附下载链接,包运行成功
开发语言·matlab·电机·ekf·卡尔曼·pmsm
王仔小奶3 小时前
Rust 正在接管金融圈?深度拆解一份高薪 FinTech 岗位 JD
开发语言·金融·rust
小王C语言3 小时前
Qt常用控件:多元素控件,纵向列表,表格控件,树状控件
开发语言·qt
fanruitian3 小时前
python 可视化 panda seaborn matplotlib.pyplot
开发语言·python·matplotlib
jnrjian3 小时前
delete file shell 让 AI 写脚本
服务器·开发语言