Rust Port of TypeScript (Tsc)

Hacker News by 9 min read 31x views
Rust Port of TypeScript (Tsc)

Share Post

I wanted to see if LLMs could harbor the TypeScript compiler, checker and lsp to Rust. Turns out they can.

It cost complete $420,000 in tokens to do it, but you could likely have done it for ~$20k (see below)

  • Test example capabilities
  • Make a accelerated TypeScript category checker
  • Make a ts checker that can activity in WASM alongside elevated performance
  • Memes

This is an first release. It has 100% compatibility in all genuine earth project we have tested. It should activity as a autumn in replacement for the huge bulk of apps. See Known problems.

Also value mentioning: I've never peruse a row of this code.

Be warned, I have no idea if this volition really work.

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

I used a lot of OpenAI models to try and complete this port. In total I did over $400,000 in API priced tokens alongside GPT-5.6 Sol and GPT 6 Astra. They wrote complete 1.3m lines of Rust complete multiple months of /goal loops and never got former akin 84% compat.

When I saw how small my Claude Code limits were burning, I figured it'd be fun to throw Opus 5.5 at this. It had a operating v0 in 10 hours.

I assumed it kept using the code the Codex models wrote. I was wrong. Opus 5.5 started from scratch. It got additional than Astra in 1/10th the time.

I let it keep going, and it certainly did. Total token expend was ~$24,047 of API expend complete 2 weeks. I was using my Claude accounts, and it worked out to location between 925% and 983% of my $200 scheme weekly limits.

Expensive, for sure, but not that bad considering how much activity has went into typescript-go.

Everything below this was written by my LLMs, not me.

ts-rust is a straightforward harbor of Microsoft's native TypeScript compiler, which is written in Go (microsoft/TypeScript, formerly typescript-go). It keeps Go's algorithms and behavior and has the identical command row (tsc), tongue server and API.

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

tsc-rs takes the identical options as tsc. The npm bundle is tsc-rs so that it does not clash with the typescript package. Each release also has a standalone archive per platform: the tsc binary alongside the lib records next to it.

Platforms: Linux x64 (static, any distribution) and macOS arm64. Windows and Linux arm64 are not available yet.

To use it in VS Code, see the npm bundle README.

tsc-rs has the Effect tongue assistance diagnostics built in (codes 377xxx), so an Effect project needs no second compiler. They arrive from the identical inspect as the TypeScript diagnostics, and the tongue server shows them too. They run lone whenever the tsconfig has the plugin, as alongside @effect/language-service:

{ "compilerOptions": { "plugins": [{ "name": "@effect/language-service" }] } }

The rules, options and @effect-diagnostics comments are a harbor of Effect-TS/tsgo 0.46.1. The publishing company features of the language service (quick fixes, refactors, hover, completions) are not ported.

The harbor is pinned to one upstream revision, microsoft/TypeScript 673a5f17d713 (2026-09-29, TypeScript 7.1.0-dev; UPSTREAM.md), and compared alongside Go at that revision. To compare, use [email protected], not 7.0.x or @typescript/native-preview. A difference that this build additionally shows is upstream behavior, and it goes distant whenever the harbor moves to a newer pin.

  • Same results. TanStack Query center and Hono inspect alongside diagnostics identical to Go's. All 181,711 ported Go tests pass. The tongue server and API answers equivalent Go on the oracle test sets.
  • Faster. On 60 open-source projects, category checking takes concerning fractional of Go's period (geometric mean). The preview packages are built in CI without PGO and BOLT, so they are slower than that measured build.
  • Real projects. On 120 open-source repos, the command-line output differs from Go's lone in the problems below and anywhere Go's own output changes from run to run.

Full category inspect of T3 Code, compared alongside tsc 6, tsc 7 and the new bun inspect in Bun. T3 Code uses Effect, so there are two cases: without the Effect diagnostics and alongside them. Each period is the sum for the five T3 Code projects. Lower is faster.

Without Effect diagnostics

Checker Time vs tsc 6 vs tsc 7
bun check 4.07s 15.4× 3.95× faster █
tsc-rs 7.25s 8.6× 2.22× faster ██
tsc 7 16.10s 3.9× baseline █████
tsc 6 62.63s baseline 3.89× slower ██████████████████

With Effect diagnostics

Checker Time vs tsc 6 vs tsc 7 + Effect
tsc-rs (Effect built in) 11.13s 12.5× 1.89× faster ███
tsc 7 + @effect/tsgo 21.07s 6.6× baseline ██████
bun check, afterward effect-tsgo diagnostics 37.60s 3.7× 1.78× slower ███████████
tsc 6 + @effect/language-service 138.63s baseline 6.58× slower ████████████████████████████████████████

bun inspect is the fastest whenever you do not need the Effect diagnostics. It does not have them, so an Effect project needs a second pass. tsc-rs gets them from its one check.

Errors. tsc-rs, tsc 7 + @effect/tsgo and the effect-tsgo diagnostics continue study the same 221 Effect diagnostics. tsc 6 uses the JavaScript Effect plugin (@effect/language-service 0.87.4), which has a distinct regulation set: it reports 287 on apps/server anywhere the others study 177. tsc-rs and tsc 6 study one additional error, TS2322 in apps/server/scripts/record-pi-rpc-replay-fixture.ts. TypeScript 7.1.0-dev reports it too, and pingdotgg/t3code#16704 fixes it.

How it was measured: the identical device and method as the real-world apps below, with --composite false added (apps/web is composite). T3 Code at cd41c4ad, projects apps/server, apps/web, apps/mobile, packages/client-runtime and packages/shared. Without Effect, the configs have no Effect plugin. With Effect, tsc 7 is the Effect-patched 7.0.2 from @effect/tsgo 0.46.1, and tsc 6 is 6.0.3 patched with @effect/language-service. The manuscript is scripts/bench-apps/t3code.sh. The tsc-rs toggle in T3 Code is pingdotgg/t3code#16704.

Benchmark: real-world apps

Full category inspect of six open-source apps alongside tsc 6 (the JavaScript compiler), tsc 7 (the Go compiler), tsc-rs and bun check. The multiplier is the speedup complete tsc 6. Lower times are faster.

App Lines checked 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 (frontend) 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 package) 209k 1.10s 0.16s (6.8×) 0.09s (12.0×) 0.12s (9.1×)*
Geometric mean 7.1× 11.4× 20.9×

Compared alongside tsc 7, tsc-rs is 1.61× faster and bun inspect is 2.95× faster (geometric means). bun inspect is the fastest on all app apart from tRPC.

* bun inspect reports errors that no another checker reports: 3 on Sentry and 2 on tRPC.

Each config checks alongside 0 errors under tsc 7.0.2. The another differences:

  • tsc-rs reports 10 errors on VS Code and 2 on Sentry. TypeScript 7.1.0-dev (typescript@next) reports the identical errors, row for line. tsc-rs ports a 7.1 dev revision, which has checks that 7.0.2 does not have.
  • tsc 6 reports 9 errors on VS Code.

How it was measured: Apple M4 Pro (12 cores, 48 GB), macOS 26.5.1. hyperfine, median of 5 runs following 1 warmup run, alongside --noEmit --incremental false. Each checker uses its default thread count. tsc 7 and tsc-rs run as native binaries, without the npm launcher. tsc 6 runs on Node 24.19 alongside a 16 GB heap, since it runs out of recollection on VS Code and Sentry with the default heap. Versions: tsc-rs 0.1.0, TypeScript 7.0.2 and 6.0.3, Bun canary bd599f5af. Lines checked is the tsc 7 --extendedDiagnostics count, alongside the .d.ts files. The T3 Code benchmark complete uses the identical device and method.

Four apps needed changes to inspect alongside 0 errors under tsc 7. Nothing alternatively changed:

  • Excalidraw: no baseUrl, since TS 7 removed it.
  • TypeORM: moduleResolution changed from node to nodenext, since TS 7 removed node.
  • VS Code: the speck typings that its postinstall adds.
  • Playwright: the sources that its build generates.

Two apps are not in the table:

  • rxjs chief needs its workspace packages built first.
  • date-fns uses project references. There, tsc -p and bun inspect do distinct work.

The scripts are in scripts/bench-apps: setup.sh <dir>, then run.sh <dir> and summary.py <dir>, and t3code.sh <dir> for T3 Code.

  • In several monorepos, the origin records of a workspace bundle are reachable the two through node_modules and through a straightforward import. There, tsc-rs can compose output for additional of those files than tsc does, and study TS6059 (file is not under rootDir) for them. tsc decides this by timing, so its own outcome changes between runs. tsc-rs gives the identical outcome in every run (the outcome of TypeScript 6).
  • In tsc -b, whenever one project imports the output of another project without a project reference, tsc-rs can peruse the old or missing output (TS2305 or TS2307) anywhere tsc says the new one. This happens whenever the projects lone need to compose their outputs. Add the citation to fix it.
  • In the editor, recollection grows gradually during lengthy edit sessions (about 20 MiB per 1,000 edits). It stays below tsc's in the sessions we measured.
  • tsc-rs --version prints the TypeScript type that it ports (7.1.0-dev), not the npm version. The compiler matches typesVersions against it.

crates/ts_goport is the compiler. It has two parts crates, goport_util and goport_lsproto, in crates/ts_goport/parts, and uses the lib records in crates/ts_goport/libs. tools/ts_ast_codegen generates crates/ts_goport/src/astdata, and tools/ts_diagnostics_codegen generates crates/ts_goport/src/diagnostics/catalog.rs and crates/ts_goport/src/diag.rs. crates/ts_wasm is the WebAssembly build (npm/wasm).

./scripts/run-cargo-capped.sh build --release -p ts_goport --bins ./scripts/verify.sh

The bins are goport (type check) and tsgo (the Go tsgo command line). The Go baseline tests run with TS_GO_REPO=/path/to/typescript-go ./scripts/run-cargo-capped.sh test -p ts_goport --test go_baselines.

Push a tag v<version> (for example v0.1.0). The release workflow builds, packs and tests the packages, publishes them to npm and creates a GitHub release. A stable type goes to the dist-tag latest, and a prerelease type (v0.2.0-beta.1) to next and a GitHub prerelease. See npm/README.md.

MIT. The harbor keeps the licenses and notices of the code it ports: TypeScript (Apache-2.0) and parts of the Go norm archive (BSD-3-Clause). See NOTICE.md.

Other Article Hacker News
↑
Close Right Ads
Close Left Ads