ts-rust(又名 tsc-rs)
我想看看 LLM 能否把 TypeScript 编译器、检查器和 lsp 移植到 Rust。事实证明它们可以。
它花费了超过 420,000 美元的 token 才完成,但你大概用约 20,000 美元就能做到(见下文)
动机
- 测试模型能力
- 做一个快速的 TypeScript 类型检查器
- 做一个能在 WASM 中高性能运行的 ts 检查器
- 梗图
警告
这是一个早期版本。在我们测试过的每个真实世界项目中,它都有 100% 的兼容性。它应该可以作为绝大多数应用的直接替代品。见已知问题。
另外值得一提的是:我从未读过这代码的一行。
安装
提前警告,我不知道这到底能不能用。
npm install -D tsc-rs npx tsc-rs -p tsconfig.json
进展如何?
我用了大量 OpenAI 模型来尝试完成这次移植。总共我用了超过 400,000 美元的 API 计价 token,用的是 GPT-5.6 Sol 和 GPT 6 Astra。它们在数月的 /goal 循环中写了超过 130 万行 Rust,兼容性却从未超过大约 84%。
当我看到我的 Claude Code 限额消耗得那么少时,我想把 Opus 5.5 扔进去应该会很有趣。它 10 小时就有了可用的 v0。
我以为它会继续使用 Codex 模型写的代码。我错了。Opus 5.5 从零开始。它用 1/10 的时间就比 Astra 走得更远。
我让它继续跑,它确实做到了。总 token 花费为2 周内约 24,047 美元的 API 花费。我用的是我的 Claude 账户,算下来大约是我 200 美元套餐每周限额的925% 到 983%。
确实很贵,但考虑到投入到 typescript-go 的工作量,也不算太糟。
“垃圾线”
以下所有内容都是由我的 LLM 写的,不是我。
这到底是什么?
ts-rust 是微软原生 TypeScript 编译器的直接移植,后者是用 Go 写的(microsoft/TypeScript,原名typescript-go)。它保留了 Go 的算法和行为,并拥有相同的命令行(tsc)、语言服务器和 API。
安装
npm install -D tsc-rs npx tsc-rs -p tsconfig.json
tsc-rs接受与tsc相同的选项。npm 包是tsc-rs这样它就不会与typescript包冲突。每个发布版本还附带各平台的独立归档:tsc二进制文件,旁边是 lib 文件。
平台:Linux x64(静态,适用于任何发行版)和 macOS arm64。Windows 和 Linux arm64 尚不可用。
要在 VS Code 中使用它,请参阅npm 包 README。
Effect 诊断
tsc-rs内置了Effect语言服务诊断(代码 377xxx),因此 Effect 项目不需要第二个编译器。它们与 TypeScript 诊断来自同一次检查,语言服务器也会显示它们。它们仅在 tsconfig 中带有该插件时运行,与@effect/language-service一样:
{ "compilerOptions": { "plugins": [{ "name": "@effect/language-service" }] } }规则、选项和@effect-diagnostics注释是Effect-TS/tsgo0.46.1 的移植。语言服务的编辑器功能(快速修复、重构、悬停、补全)未被移植。
状态
该移植固定在一个上游修订版本,microsoft/TypeScript673a5f17d713(2026-09-29,TypeScript 7.1.0-dev;UPSTREAM.md),并在该修订版本上与 Go 进行比较。要进行比较,请使用typescript@7.1.0-dev.20260929.1,而不是 7.0.x 或@typescript/native-preview。此构建也显示出的差异属于上游行为,当移植移动到更新的固定版本时它会消失。
- 结果相同。TanStack Query core 和 Hono 的检查诊断与 Go 完全相同。所有 181,711 个移植的 Go 测试均通过。语言服务器和 API 的答案在 oracle 测试集上与 Go 一致。
- 更快。在 60 个开源项目上,类型检查耗时约为 Go 的一半(几何平均值)。预览包在 CI 中构建,未使用 PGO 和 BOLT,因此比该测量构建更慢。
- 真实项目。在 120 个开源仓库上,命令行输出与 Go 的差异仅在于下面的问题以及 Go 自身输出每次运行会变化的地方。
基准测试:T3 Code
完整类型检查T3 Code,与tsc6、tsc7bun check以及 Bun 中新的
进行比较。T3 Code 使用 Effect,因此有两种情况:不带 Effect 诊断和带 Effect 诊断。每次时间是五个 T3 Code 项目的总和。越低越快。
| 不带 Effect 诊断 | 检查器 | 时间tsc对比 |
6tsc对比 |
|
|---|---|---|---|---|
bun check |
4.07s | 15.4× | 快 3.95× | █ |
tsc-rs |
7.25s | 8.6× | 快 2.22× | ██ |
tsc7 |
16.10s | 3.9× | 基准 | █████ |
tsc6 |
62.63s | 基准 | 慢 3.89× | ██████████████████ |
带 Effect 诊断
| 检查器 | 时间 | 对比tsc6 |
对比tsc7 + Effect |
|
|---|---|---|---|---|
tsc-rs(内置 Effect) |
11.13s | 12.5× | 快 1.89× | ███ |
tsc7 +@effect/tsgo |
21.07s | 6.6× | 基准 | ██████ |
bun check,然后effect-tsgo diagnostics |
37.60s | 3.7× | 慢 1.78× | ███████████ |
tsc6 +@effect/language-service |
138.63s | 基准 | 慢 6.58× | ████████████████████████████████████████ |
bun check在你不需要 Effect 诊断时是最快的。它没有这些诊断,因此 Effect 项目需要第二遍。tsc-rs从它的一次检查中获得它们。
错误。tsc-rs、tsc7 +@effect/tsgo以及effect-tsgo diagnostics报告相同的 221 个 Effect 诊断。tsc6 使用 JavaScript Effect 插件(@effect/language-service0.87.4),它有另一套规则集:它报告 287 个apps/server而其他工具报告 177 个。tsc-rs以及tsc6 多报告一个错误,TS2322 在apps/server/scripts/record-pi-rpc-replay-fixture.ts。TypeScript 7.1.0-dev 也报告了它,并且pingdotgg/t3code#16704修复了它。
测量方式:与下方真实应用相同的机器和方法,加上--composite false添加了(apps/web是 composite)。T3 Code 在cd41c4ad,
projectsapps/server,apps/web,apps/mobile,packages/client-runtime以及packages/shared。没有 Effect 时,这些配置没有 Effect 插件。有 Effect 时,tsc7 是来自@effect/tsgo0.46.1 的 Effect 补丁版 7.0.2,并且tsc6 是 6.0.3 打了补丁,使用@effect/language-service。脚本是scripts/bench-apps/t3code.sh。tsc-rsT3 Code 中的开关是pingdotgg/t3code#16704。
基准测试:真实应用
对六个开源应用进行完整类型检查,使用tsc6(JavaScript 编译器)、tsc7(Go 编译器)、tsc-rs以及bun check。倍数是相对于tsc6 的加速比。时间越低越
| 快。 | 应用 | tsc检查行数 |
tsc6 |
tsc-rs |
bun check |
|---|---|---|---|---|---|
| 7 | VS Code | 3.75M | 54.56s | 6.84s(8.0×) | 4.20s(13.0×) |
| 1.62s(33.7×)Sentry | (前端) | 2.11M | 58.76s | 7.90s(7.4×) | 4.46s(13.2×) |
| 3.14s(18.7×)* | Playwright | 585k | 4.48s | 0.66s(6.8×) | 0.34s(13.2×) |
| 0.18s(25.0×) | Excalidraw | 449k | 5.32s | 0.80s(6.7×) | 0.70s(7.6×) |
| 0.18s(29.0×) | TypeORM | 386k | 3.86s | 0.55s(7.0×) | 0.36s(10.7×) |
| 0.19s(20.0×)tRPC | (server 包) | 209k | 1.10s | 0.16s(6.8×) | 0.09s(12.0×) |
| 0.12s(9.1×)* | 几何平均 | 7.1× | 11.4× |
20.9×tsc与tsc-rs7 相比,bun check快 1.61×,bun check快 2.95×(几何
平均)。bun check在除 tRPC 外的每个应用上都是最快的。
*tsc报告了其他检查器都没有报告的错误:Sentry 上 3 个,tRPC 上 2 个。
tsc-rs每个配置在typescript@next7.0.2 下检查均为 0 错误。其他差异:tsc-rs在 VS Code 上报告 10 个错误,在 Sentry 上报告 2 个。TypeScript 7.1.0-dev(tsc)逐行报告相同的错误。
移植了一个 7.1 开发修订版,其中包含7.0.2 没有的检查。6 在 VS Code 上报告 9 个错误。--noEmit --incremental false测量方式:Apple M4 Pro(12 核,48 GB),macOS 26.5.1。tschyperfinetsc-rs,1 次预热运行后取 5 次运行的中位数,使用tsc。每个检查器使用其tsc-rs默认线程数。bd599f5af7 和tsc以原生二进制运行,不使用 npm 启动器。--extendedDiagnostics6 在 Node 24.19 上运行,堆大小为 16 GB,因为在默认堆下它在 VS Code 和 Sentry 上会内存耗尽。版本:.d.ts0.1.0、TypeScript 7.0.2 和 6.0.3、Bun canary
。检查行数是tsc7
- 计数,包含
baseUrl文件。 上方的 T3 Code 基准测试使用相同的机器和方法。 - TypeORM:
moduleResolution从node改为nodenext,因为 TS 7 移除了node。 - VS Code:
electron其 postinstall 添加的类型声明。 - Playwright:其构建生成的源码。
有两个应用不在表中:
- rxjs main 需要先构建其工作区包。
- date-fns 使用项目引用。在那里,
tsc -p和bun check做不同的工作。
脚本位于scripts/bench-apps:setup.sh <dir>,然后run.sh <dir>和summary.py <dir>,以及t3code.sh <dir>用于 T3 Code。
已知问题
- 在某些 monorepo 中,工作区包的源文件既可以通过
node_modules访问,也可以通过直接导入访问。在那里,tsc-rs可以为更多此类文件写入输出,比tsc更多,并为其报告 TS6059(文件不在rootDir下)。tsc通过计时来决定这一点,因此它自身的结果在多次运行之间会变化。tsc-rs在每次运行中给出相同结果(TypeScript 6 的结果)。 - 在
tsc -b中,当一个项目导入另一个项目的输出而没有项目引用时,tsc-rs可能读到旧的或缺失的输出(TS2305 或 TS2307),而tsc读到的是新的。当这些项目只需要写入其输出时会发生这种情况。添加引用即可修复。 - 在编辑器中,长时间编辑会话期间内存会缓慢增长(每 1,000 次编辑约 20 MiB)。在我们测量的会话中,它保持在
tsc的水平以下。 tsc-rs --version打印的是它所移植的 TypeScript 版本(7.1.0-dev),而不是 npm 版本。编译器会据此匹配typesVersions。
开发
crates/ts_goport就是编译器。它有两个部分 crate,goport_util和goport_lsproto,位于crates/ts_goport/parts中,并使用crates/ts_goport/libs中的 lib 文件。tools/ts_ast_codegen生成crates/ts_goport/src/astdata,而tools/ts_diagnostics_codegen生成crates/ts_goport/src/diagnostics/catalog.rs和crates/ts_goport/src/diag.rs。crates/ts_wasm是 WebAssembly 构建(npm/wasm)。
./scripts/run-cargo-capped.sh build --release -p ts_goport --bins ./scripts/verify.sh
这些 bin 是goport(类型检查)和tsgo(Gotsgo命令行)。Go 基线测试使用TS_GO_REPO=/path/to/typescript-go ./scripts/run-cargo-capped.sh test -p ts_goport --test go_baselines运行。
- 移植规则:crates/ts_goport/PORTING.md
- 测量和门禁脚本:scripts/goport
- npm 包和发布:npm/README.md
- 类型检查器工作规则:AGENTS.md,问责规则以及保存的状态
- 项目如何开始:docs/history.md
发布
推送一个 tagv<version>(例如v0.1.0)。发布工作流构建、打包并测试这些包,将它们发布到 npm 并创建 GitHub release。稳定版本进入 dist-taglatest,而预发布版本(v0.2.0-beta.1)进入next以及一个 GitHub prerelease。参见npm/README.md。
许可证
MIT。该移植保留了它所移植代码的许可证和声明:TypeScript(Apache-2.0)以及 Go 标准库的部分内容(BSD-3-Clause)。参见NOTICE.md。