An experimental Rust port of the TypeScript 7 compiler (tsc)
Rust
328
5,847 commits
updated Oct 7, 2026
I wanted to see if LLMs could port the TypeScript compiler, checker and lsp to Rust. Turns out they can.
It cost over $420,000 in tokens to do it, but you could probably have done it for ~$20k (see below)
This is an early release. It is not yet a full replacement for tsc in every project. See
Known problems.
Also worth mentioning: I've never read a line of this code.
Be warned, I have no idea if this will actually work.
npm install -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 with GPT-5.6 Sol and GPT 6 Astra. They wrote over 1.3m lines of Rust over multiple months of /goal loops and never got past like 84% compat.
When I saw how little my Claude Code limits were burning, I figured it'd be fun to throw Opus 5.5 at this. It had a working 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 further than Astra in 1/10th the time.
I let it keep going, and it definitely did. Total token spend was ~$24,047 of API spend over 2 weeks. I was using my Claude accounts, and it worked out to somewhere between 925% and 983% of my $200 plan weekly limits.
Expensive, for sure, but not that bad considering how much work has went into typescript-go.
Everything below this was written by my LLMs, not me.
ts-rust is a direct port 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 same command line (tsc), language server and API.
npm install -D tsc-rs
npx tsc-rs -p tsconfig.json
tsc-rs takes the same options as tsc. The npm package 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 with the lib files 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 package README.
tsc-rs has the Effect language service diagnostics built in (codes
377xxx), so an Effect project needs no second compiler. They come from the same check as the
TypeScript diagnostics, and the language server shows them too. They run only when the tsconfig has
the plugin, as with @effect/language-service:
{ "compilerOptions": { "plugins": [{ "name": "@effect/language-service" }] } }
The rules, options and @effect-diagnostics comments are a port of
Effect-TS/tsgo 0.46.1. The editor features of the language
service (quick fixes, refactors, hover, completions) are not ported.
The port is pinned to one upstream revision (UPSTREAM.md) and compared with Go at that revision:
Full type check of T3 Code, compared with tsc 6, tsc 7
and the new bun check in Bun. T3 Code uses Effect, so there are two cases: without the Effect
diagnostics and with them. Each time 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, then effect-tsgo diagnostics | 37.60s | 3.7× | 1.78× slower | ███████████ |
tsc 6 + @effect/language-service | 138.63s | baseline | 6.58× slower | ████████████████████████████████████████ |
bun check is the fastest when 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 pass report the same
221 Effect diagnostics. tsc 6 uses the JavaScript Effect plugin
(@effect/language-service 0.87.4), which has a different rule set: it reports 287 on
apps/server where the others report 177. tsc-rs and tsc 6 report one more 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 same machine 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 script is
scripts/bench-apps/t3code.sh. The tsc-rs switch in T3 Code is
pingdotgg/t3code#16704.
Full type check of six open-source apps with tsc 6 (the JavaScript compiler), tsc 7 (the Go
compiler), tsc-rs and bun check. The multiplier is the speedup over 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 with tsc 7, tsc-rs is 1.61× faster and bun check is 2.95× faster (geometric
means). bun check is the fastest on every app except tRPC.
* bun check reports errors that no other checker reports: 3 on Sentry and 2 on tRPC.
Each config checks with 0 errors under tsc 7.0.2. The other differences:
tsc-rs reports 10 errors on VS Code and 2 on Sentry. TypeScript 7.1.0-dev (typescript@next)
reports the same errors, line 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 after 1 warmup run, with --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 with a 16 GB heap, because it runs out of memory 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, with the .d.ts files.
The T3 Code benchmark above uses the same machine and method.
Four apps needed changes to check with 0 errors under tsc 7. Nothing else changed:
baseUrl, because TS 7 removed it.moduleResolution changed from node to nodenext, because TS 7 removed node.electron typings that its postinstall adds.Two apps are not in the table:
tsc -p and bun check do different 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.
node_modules and through a direct import. There, tsc-rs can write output for more of those
files than tsc does.tsc -b, when one project imports the output of another project without a project reference,
tsc-rs can report TS2307 (cannot find module) where tsc happens to build the other project
first. Add the reference to fix it.tsc -b --watch can stop with an internal error (exit code 70) after some edits.tsc-rs --version prints the TypeScript version 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 files 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 version goes to the dist-tag latest, and a
prerelease version (v0.2.0-beta.1) to next and a GitHub prerelease. See
npm/README.md.
MIT. The port keeps the licenses and notices of the code it ports: TypeScript (Apache-2.0) and parts of the Go standard library (BSD-3-Clause). See NOTICE.md.
An experimental Rust port of the TypeScript 7 compiler (tsc)
Rust
328
5,847 commits
updated Oct 7, 2026
I wanted to see if LLMs could port the TypeScript compiler, checker and lsp to Rust. Turns out they can.
It cost over $420,000 in tokens to do it, but you could probably have done it for ~$20k (see below)
This is an early release. It is not yet a full replacement for tsc in every project. See
Known problems.
Also worth mentioning: I've never read a line of this code.
Be warned, I have no idea if this will actually work.
npm install -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 with GPT-5.6 Sol and GPT 6 Astra. They wrote over 1.3m lines of Rust over multiple months of /goal loops and never got past like 84% compat.
When I saw how little my Claude Code limits were burning, I figured it'd be fun to throw Opus 5.5 at this. It had a working 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 further than Astra in 1/10th the time.
I let it keep going, and it definitely did. Total token spend was ~$24,047 of API spend over 2 weeks. I was using my Claude accounts, and it worked out to somewhere between 925% and 983% of my $200 plan weekly limits.
Expensive, for sure, but not that bad considering how much work has went into typescript-go.
Everything below this was written by my LLMs, not me.
ts-rust is a direct port 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 same command line (tsc), language server and API.
npm install -D tsc-rs
npx tsc-rs -p tsconfig.json
tsc-rs takes the same options as tsc. The npm package 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 with the lib files 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 package README.
tsc-rs has the Effect language service diagnostics built in (codes
377xxx), so an Effect project needs no second compiler. They come from the same check as the
TypeScript diagnostics, and the language server shows them too. They run only when the tsconfig has
the plugin, as with @effect/language-service:
{ "compilerOptions": { "plugins": [{ "name": "@effect/language-service" }] } }
The rules, options and @effect-diagnostics comments are a port of
Effect-TS/tsgo 0.46.1. The editor features of the language
service (quick fixes, refactors, hover, completions) are not ported.
The port is pinned to one upstream revision (UPSTREAM.md) and compared with Go at that revision:
Full type check of T3 Code, compared with tsc 6, tsc 7
and the new bun check in Bun. T3 Code uses Effect, so there are two cases: without the Effect
diagnostics and with them. Each time 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, then effect-tsgo diagnostics | 37.60s | 3.7× | 1.78× slower | ███████████ |
tsc 6 + @effect/language-service | 138.63s | baseline | 6.58× slower | ████████████████████████████████████████ |
bun check is the fastest when 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 pass report the same
221 Effect diagnostics. tsc 6 uses the JavaScript Effect plugin
(@effect/language-service 0.87.4), which has a different rule set: it reports 287 on
apps/server where the others report 177. tsc-rs and tsc 6 report one more 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 same machine 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 script is
scripts/bench-apps/t3code.sh. The tsc-rs switch in T3 Code is
pingdotgg/t3code#16704.
Full type check of six open-source apps with tsc 6 (the JavaScript compiler), tsc 7 (the Go
compiler), tsc-rs and bun check. The multiplier is the speedup over 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 with tsc 7, tsc-rs is 1.61× faster and bun check is 2.95× faster (geometric
means). bun check is the fastest on every app except tRPC.
* bun check reports errors that no other checker reports: 3 on Sentry and 2 on tRPC.
Each config checks with 0 errors under tsc 7.0.2. The other differences:
tsc-rs reports 10 errors on VS Code and 2 on Sentry. TypeScript 7.1.0-dev (typescript@next)
reports the same errors, line 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 after 1 warmup run, with --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 with a 16 GB heap, because it runs out of memory 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, with the .d.ts files.
The T3 Code benchmark above uses the same machine and method.
Four apps needed changes to check with 0 errors under tsc 7. Nothing else changed:
baseUrl, because TS 7 removed it.moduleResolution changed from node to nodenext, because TS 7 removed node.electron typings that its postinstall adds.Two apps are not in the table:
tsc -p and bun check do different 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.
node_modules and through a direct import. There, tsc-rs can write output for more of those
files than tsc does.tsc -b, when one project imports the output of another project without a project reference,
tsc-rs can report TS2307 (cannot find module) where tsc happens to build the other project
first. Add the reference to fix it.tsc -b --watch can stop with an internal error (exit code 70) after some edits.tsc-rs --version prints the TypeScript version 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 files 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 version goes to the dist-tag latest, and a
prerelease version (v0.2.0-beta.1) to next and a GitHub prerelease. See
npm/README.md.
MIT. The port keeps the licenses and notices of the code it ports: TypeScript (Apache-2.0) and parts of the Go standard library (BSD-3-Clause). See NOTICE.md.