Default threading differs: tsgo and tsc-rs default to 4 checkers; tsc-ts, tsrs and bun use one per core, up to 10 on this 10-core machine (sources). The other settings give every checker the same thread count, set with its documented flag. ¹ marks a checker that reported errors where tsgo reported none.
VS Code
The VS Code editor's main sources. 10,645 project files. tsgo creates 3.3 M types and 4.2 M instantiations.
tsc-rs and tsrs report 10 errors that tsgo 7.0.2 does not; their upstream TypeScript builds print exactly the same (details).
Checked with -p ./src/tsconfig.json --noEmit --skipLibCheck at 4a82da11e45f, from package.json typecheck-client. Raw: timings, diagnostics, file lists, work counts.
Outline
A knowledge-base web app. 2,315 project files. tsgo creates 0.6 M types and 5.8 M instantiations.
tsc-rs and tsrs report 1 error that tsgo 7.0.2 does not; their upstream TypeScript builds print exactly the same (details).
Checked with -p . --incremental false at ef7753dc57a6, from .github/workflows/ci.yml, job types: yarn tsc --incremental false. Raw: timings, diagnostics, file lists, work counts.
type-fest
A type-level library; its check cost is almost all its own test-d suite. 502 project files. tsgo creates 5.9 M types and 17.8 M instantiations.
tsc-rs and tsrs print one type differently in a message with the planted errors; their upstream TypeScript builds print exactly the same (details).
Checked with -p . --noEmit at b550b410e13f, from package.json test:tsc (tsc on the repo tsconfig, which sets noEmit). Raw: timings, diagnostics, file lists, work counts.
All 3 projects against tsgo
tsgo's median wall time divided by each checker's, so 2.0× means the checker took half as long.
| VS Code | Outline | type-fest | |
|---|---|---|---|
| tsc-ts | 2.2× | 3.7× | 4.5× |
| tsc-rs | 2.4× | 2.5× | 3.3× |
| tsrs | 5.8× | 5.6× | 4.3× |
| bun | 3.3× | 3.7× | 5.7× |
| VS Code | Outline | type-fest | |
|---|---|---|---|
| tsc-ts | 1.2× | 2.1× | 2.5× |
| tsc-rs | 2.0× | 2.5× | 3.5× |
| tsrs | 3.2× | 3.7× | 2.9× |
| bun | 1.7× | 2.4× | 3.3× |
| VS Code | Outline | type-fest | |
|---|---|---|---|
| tsc-ts | 1.5× | 3.0× | 3.4× |
| tsc-rs | 2.4× | 2.4× | 3.2× |
| tsrs | 4.2× | 5.1× | 4.1× |
| bun | 2.2× | 2.6× | 4.6× |
| VS Code | Outline | type-fest | |
|---|---|---|---|
| tsc-ts | 2.1× | 3.4× | 3.4× |
| tsc-rs | 2.7× | 2.8× | 3.5× |
| tsrs | 5.6× | 5.1× | 3.2× |
| bun | 3.2× | 3.4× | 4.2× |
Do they report the same errors?
Each checker ran every project clean and with a few planted type errors, and its output was compared with tsgo's.
- tsc-tsIdentical to tsgo
Byte-for-byte the same output as tsgo on all 3 projects, clean and with planted errors.
- tsc-rsSame as the TypeScript build it ports
Reports errors tsgo 7.0.2 does not: 10 on VS Code and 1 on Outline. One message prints a type differently on type-fest. Upstream tsgo built from the TypeScript commit it ports,
typescript@7.1.0-dev.20261008.1, prints exactly the same output on every project, so these differences come from that TypeScript version, not from tsc-rs. - tsrsSame as the TypeScript build it ports
Reports errors tsgo 7.0.2 does not: 10 on VS Code and 1 on Outline. One message prints a type differently on type-fest. Upstream tsgo built from the TypeScript commit it ports,
typescript@7.1.0-dev.20260930.4, prints exactly the same output on every project, so these differences come from that TypeScript version, not from tsrs. - bunSame errors as tsgo
Prints tsgo's error lines word for word on all 3 projects, and adds its own summary of the check.
Per project and state
| VS Code | Outline | type-fest | ||||
|---|---|---|---|---|---|---|
| clean0 errors | planted3 errors | clean0 errors | planted3 errors | clean0 errors | planted6 errors | |
| tsc-ts | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|---|
| tsc-rs | +10 | +10 | +1 | +1 | ✓ | +1 −1 |
|---|---|---|---|---|---|---|
| its upstream buildupstream | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| tsrs | +10 | +10 | +1 | +1 | ✓ | +1 −1 |
|---|---|---|---|---|---|---|
| its upstream buildupstream | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| bun | ≈ | ≈ | ≈ | ≈ | ≈ | ≈ |
|---|
✓ byte-identical to tsgo≈ same errors, places and top-level messages after normalising each output to one path:line:col code message line per error+n −m lines only in the checker, only in tsgoThe counts under each column are tsgo's errors. Ports get a second row against their upstream build.
Every difference, verbatim, and the full tables, in the run's report.
Checkers
- tsgoreference
typescript@7.0.2Microsoft's native TypeScript 7 compiler (Go).
Default threading: 4 checkers. Thread flags used:
--singleThreadedand--checkers N. - tsc-ts
tsc-ts@0.0.3A TypeScript port of tsgo 7.0.2, compiled to a native executable with scriptc (Vercel Labs).
Default threading: one per core (10 here). Thread flags used:
--singleThreadedand--checkers N. - tsc-rs
tsc-rs@0.7.0A Rust port of the TypeScript 7 compiler (pingdotgg/ts-rust).
Default threading: 4 checkers. Thread flags used:
--singleThreadedand--checkers N. - tsrs
tsrs@0.16.0-ts7.1.0-dev.20260929A Rust port of the TypeScript 7 compiler (oxc-project).
Default threading: one per core (10 here). Thread flags used:
--singleThreadedand--checkers N. - bun
bun@1.4.3Bun's built-in type checker (bun check).
Default threading: one per core (10 here). Thread flags used:
--threads=1and--threads=N.
Diagnostics only, never timed: upstream tsgo typescript@7.1.0-dev.20260930.4, the build tsrs ports; typescript@7.1.0-dev.20261008.1, the build tsc-rs ports.
Thread defaults and flags as each checker documents them (sources). Each binary's version output and sha256 are in run.json.
How it was measured
- Machine
- Apple M5, 10 cores, 24 GiBmacOS 26.5.1 (25F80)
- Each check
- A fresh process, no incremental cacheNo build info or cache carries over between runs. The OS file cache is warm for every checker alike: each set of runs starts with a warm-up round.
- Sample
- Median of 7 timed roundsAfter one warm-up round. Checker order rotated each round, so every checker ran in every position.
- Settings
- Shipped defaults, no tuning flagsEach checker as it ships, with only the project's own typecheck arguments.
- Projects
- Pinned commits, their own lockfilesBenchmarked only if tsgo reports 0 errors; rejected in this run: excalidraw.
- Conditions
- All 570 runs on AC powerKept awake by caffeinate, no sleep, wake or thermal events, no preflight warnings.
- Harness
bde799c06fc9Recorded after the run: the last harness commit before it started (details in run.json).
Caveats, and what the numbers do not show, in docs/METHOD.md. Every file behind this page is in results/2026-10-19-apple-m5-darwin/, with its full report.
Run it yourself
On macOS, Linux or Windows, with Node 22.18 or later and git. Use a quiet machine on AC power. AGENTS.md lists every prerequisite and what to check at each step.
- Get the codeClone the repository.
git clone https://github.com/danfry1/ts-checker-bench && cd ts-checker-bench - Check the harnessIts typecheck and tests, and that the committed reports regenerate exactly.
(cd bench && npm ci && npm run check) - Install everythingEvery checker from its lockfile, and every project at its pinned commit with its own install command. About 10 GB, most of it VS Code's own dependencies.
node bench setup - Check the machineRefuses to start on battery or with a checkout that is not ready; warns about busy processes.
node bench preflight - Try it end to endtype-fest only, one round, about 6 minutes. Not published.
node bench run --smoke - Run the benchmarkAbout 40 minutes on a 10-core Mac, longer on slower ones. Writes results/<date>-<cpu>-<os>/ with its report.
node bench run - Send itCheck the run as CI will, then open a pull request with its results/ folder. Runs from other machines are welcome.
node bench verify <date>-<cpu>-<os>