跳到正文
Hacker News:AI 热帖· jcbhmr·· 9 小时前精选AI 评分76

ts-rust 发布:由 LLM 将 TypeScript 编译器、检查器和 LSP 移植到 Rust

Port of the TypeScript compiler, checker and lsp to Rust, by LLM

AI 导读

ts-rust(tsc-rs)将 microsoft/TypeScript(Go 实现)的编译器、类型检查器和语言服务器移植为 Rust,作者称全部代码由 LLM 编写,本人未读过代码。

推荐理由

原文给出了完整基准数据和兼容性测试结果,读者可以据此评估这个 Rust 版 TypeScript 检查器是否适合接入现有项目。

正文 · AI 翻译

ts-rust(又名 tsc-rs)

我想看看 LLM 能否把 TypeScript 编译器、检查器和 lsp 移植到 Rust。事实证明它们可以。

这花费了超过 42 万美元的 token,但你大概用约 2 万美元就能完成(见下文)

动机

  • 测试模型能力
  • 打造一个快速的 TypeScript 类型检查器
  • 打造一个能在 WASM 中高性能运行的 ts 检查器
  • 梗图

警告

这是早期版本。在我们测试过的所有真实项目中,它都实现了 100% 兼容。对于绝大多数应用来说,它应当可以作为直接替代品使用。参见已知问题。

另外值得一提的是:这代码我一行都没读过。

安装

事先警告,我完全不知道这到底能不能用。

npm install -D tsc-rs
npx tsc-rs -p tsconfig.json

进展如何?

我用了大量 OpenAI 模型来尝试完成这次移植。总共,我用 GPT-5.6 Sol 和 GPT 6 Astra 消耗了超过 40 万美元 API 定价的 token。它们在数月的 /goal 循环中写了超过 130 万行 Rust,兼容度却始终没能超过 84% 左右。

当我看到我的 Claude Code 额度几乎没怎么消耗时,我想把 Opus 5.5 扔进去应该会很有趣。它 10 小时就做出了一个可用的 v0。

我以为它会继续使用 Codex 模型写的代码。我错了。Opus 5.5 是从零开始的。它用 1/10 的时间就比 Astra 走得更远。

我让它继续跑下去,它确实做到了。总 token 花费为两周内约 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/tsgo 0.46.1 的移植。语言服务器的编辑器功能(快速修复、重构、悬停、补全)尚未移植。

状态

该移植固定在一个上游修订版本,即 microsoft/TypeScript 673a5f17d713(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 核心和 Hono 的检查诊断与 Go 完全一致。所有 181,711 个移植的 Go 测试均通过。语言服务器和 API 的应答在 oracle 测试集上与 Go 一致。
  • 更快。在 60 个开源项目上,类型检查耗时约为 Go 版本的一半(几何平均值)。预览包是在 CI 中构建的,未启用 PGO 和 BOLT,因此比上述实测构建更慢。
  • 真实项目。在 120 个开源仓库上,命令行输出与 Go 版本的差异仅在于下述问题,以及 Go 自身输出在多次运行间发生变化之处。

基准测试:T3 Code

对 T3 Code 进行完整类型检查,并与 tsc 6、tsc 7 以及 Bun 中新的 bun check 进行对比。T3 Code 使用了 Effect,因此有两种情况:不带 Effect 诊断和带 Effect 诊断。每次耗时均为五个 T3 Code 项目的总和。越低越快。

不带 Effect 诊断

检查器 时间 对比 tsc 6 对比 tsc 7
bun check 4.07s 15.4× 快 3.95× █
tsc-rs 7.25s 8.6× 快 2.22× ██
tsc 7 16.10s 3.9× 基准 █████
tsc 6 62.63s 基准 慢 3.89× ██████████████████

带 Effect 诊断

检查器 时间 对比 tsc 6 对比 tsc 7 + Effect
tsc-rs(内置 Effect) 11.13s 12.5× 快 1.89× ███
tsc 7 + @effect/tsgo 21.07s 6.6× 基准 ██████
bun check,然后 effect-tsgo diagnostics 37.60s 3.7× 慢 1.78× ███████████
tsc 6 + @effect/language-service 138.63s 基准 慢 6.58× ████████████████████████████████████████

当你不需要 Effect 诊断时,bun check 是最快的。它没有这些诊断,因此 Effect 项目需要第二遍检查。tsc-rs 通过一次检查即可获得它们。

错误。tsc-rs、tsc 7 + @effect/tsgo 以及 effect-tsgo diagnostics 这一遍报告了相同的 221 条 Effect 诊断。tsc 6 使用 JavaScript Effect 插件(@effect/language-service 0.87.4),其规则集不同:在 apps/server 上它报告 287 条,而其他工具报告 177 条。tsc-rs 和 tsc 6 多报告一个错误,即 apps/server/scripts/record-pi-rpc-replay-fixture.ts 中的 TS2322。TypeScript 7.1.0-dev 也报告了它,pingdotgg/t3code#16704 修复了该问题。

测量方式:与下文真实应用相同的机器和方法,并添加了 --composite false(apps/web 为 composite)。T3 Code 位于 cd41c4ad,项目为 apps/server、apps/web、apps/mobile、packages/client-runtime 和 packages/shared。不带 Effect 时,配置中没有 Effect 插件。带 Effect 时,tsc 7 是来自 @effect/tsgo 0.46.1 的 Effect 补丁版 7.0.2,而 tsc 6 是用 @effect/language-service 打补丁的 6.0.3。脚本为 scripts/bench-apps/t3code.sh。T3 Code 中的 tsc-rs 开关是 pingdotgg/t3code#16704。

基准测试:真实应用

使用 tsc 6(JavaScript 编译器)、tsc 7(Go 编译器)、tsc-rs 和 bun check 对六个开源应用进行完整类型检查。倍数是相对于 tsc 6 的加速比。时间越低越快。

应用 检查行数 tsc 6 tsc 7 tsc-rs bun check
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 7 相比,tsc-rs 快 1.61×,bun check 快 2.95×(几何平均值)。除 tRPC 外,bun check 在每个应用上都是最快的。

* bun check 报告了其他检查器均未报告的错误:Sentry 上 3 个,tRPC 上 2 个。

每个配置在 tsc 7.0.2 下检查均为 0 错误。其他差异:

  • tsc-rs 在 VS Code 上报告 10 个错误,在 Sentry 上报告 2 个。TypeScript 7.1.0-dev(typescript@next)逐行报告相同的错误。tsc-rs 移植了 7.1 开发版本,其中包含 7.0.2 没有的检查。
  • tsc 6 在 VS Code 上报告 9 个错误。

测量方式:Apple M4 Pro(12 核,48 GB),macOS 26.5.1。hyperfine,1 次预热运行后取 5 次运行的中位数,使用 --noEmit --incremental false。每个检查器使用其默认线程数。tsc 7 和 tsc-rs 以原生二进制运行,不使用 npm 启动器。tsc 6 在 Node 24.19 上运行,堆大小为 16 GB,因为在 VS Code 和 Sentry 上使用默认堆会内存不足。版本:tsc-rs 0.1.0、TypeScript 7.0.2 和 6.0.3、Bun canary bd599f5af。检查的行数是 tsc 7 的 --extendedDiagnostics 计数,使用 .d.ts 文件。上面的 T3 Code 基准测试使用相同的机器和方法。

有四个应用需要修改才能在 tsc 7 下以 0 错误进行检查。其他没有变化:

  • Excalidraw:没有 baseUrl,因为 TS 7 移除了它。
  • TypeORM:moduleResolution 从 node 改为 nodenext,因为 TS 7 移除了 node。
  • VS Code:其 postinstall 添加的 electron 类型定义。
  • Playwright:其构建生成的源文件。

有两个应用不在表中:

  • rxjs main 需要先构建其工作区包。
  • date-fns 使用项目引用。在那里,tsc -p 和 bun check 做不同的工作。

脚本位于 scripts/bench-apps:setup.sh <dir>,然后是 run.sh <dir> 和 summary.py <dir>,T3 Code 用 t3code.sh <dir>。

已知问题

  • 在某些 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

二进制文件是 goport(类型检查)和 tsgo(Go tsgo 命令行)。Go 基线测试使用 TS_GO_REPO=/path/to/typescript-go ./scripts/run-cargo-capped.sh test -p ts_goport --test go_baselines 运行。

发布

推送标签 v<version>(例如 v0.1.0)。发布工作流 构建、打包并测试这些包,将它们发布到 npm 并创建 GitHub 发布。稳定版本进入 dist-tag latest,预发布版本(v0.2.0-beta.1)进入 next 和 GitHub 预发布。参见 npm/README.md。

许可证

MIT。该移植保留了它所移植代码的许可证和声明:TypeScript(Apache-2.0)和 Go 标准库的部分内容(BSD-3-Clause)。参见 NOTICE.md。

来源:Hacker News:AI 热帖 · github.com