Decision
tsrs is a Rust port of the TypeScript 7 compiler built with the TypeScript team and planned to become part of Oxc. It is experimental.tsc (TypeScript 7.0.2) stays the required type-check gate.
tsrs runs in two advisory places only:
- The pre-push gate defaults to tsc.
Explicit
--checker tsrscomparisons are advisory and always confirmed by tsc, including a tsrs pass. Resolution requires a planned qualified project; hook mode accepts only an existingTSRS_BINand never fetches packages. Clean-source parity alone does not qualify detection of seeded errors. .github/workflows/tsrs-shadow.yamlcompares tsrs withtscon main pushes that touch qualified projects and reports differences as warnings. The job iscontinue-on-errorand is not a required check.
tsrs@0.18.0-ts7.1.0-dev.20260929 (version string
7.1.0-dev.20260930.4). It is installed outside the workspace (npm install --prefix in CI, the npm exec cache locally) so the shadow never changes
bun.lock. Set TSRS_BIN to use a different binary locally.
Evaluation (2026-10-23)
Median of three cold runs per checker on a 10-core, 24 GB Apple Silicon machine,-p <project> --noEmit --incremental false --composite false, queued through
ttr resources run. Workspace dist declarations were not built (builds are
CI-only), so absolute diagnostic counts include missing-module noise; parity is
still meaningful because every checker saw the same files. Timings were taken
while other sessions shared the machine, so treat them as relative.
“Exact” compares the full diagnostic multiset including message text,
independent of order. “Location” compares file, line, column and code.
Findings:
- tsrs matches TypeScript 7.1, not 7.0. Every difference from 7.0.2 also
appears with
tsc7.1.0-beta.packages/uiandapps/webgain implicit-anydiagnostics under 7.1 semantics;apps/tasksandapps/calendardiffer only in how long types are printed. Against 7.1-beta, tsrs has location parity on all eight projects and exact parity on seven;apps/webdiffers in two messages where tsrs prints a truncated property type instead of.... - Speed and memory. tsrs is 1.3-6.3x faster (larger projects gain more) with roughly 50-70% less peak memory.
- TypeScript 7.1 beta is 1.1-1.3x faster than 7.0.2 on packages and
apps/tasks, but slower onapps/calendarandapps/webin this run, with lower memory. It is a beta and changes diagnostics, so it is not adopted. - Configuration support. All tsconfig features we use type-check the same:
package-name
extendschains,paths,NodeNext/Bundlerresolution,jsxpreserve/react-jsx,types,libincludingwebworker, JSON modules andincludeglobs.--build --dryresolves the same project-reference graph forapps/meetandapps/web.--showConfigis not supported. Emit (declarations,--buildwrites) was not evaluated because it is a build. - Exit status is 2 for diagnostics where
tsc7.0.2 returns 1; compare success versus failure, not exact codes.
Shadow job
node scripts/ci/tsrs-shadow.js runs both checkers per project, records wall
time and peak RSS (/usr/bin/time), compares diagnostic multisets and writes a
step summary, ::warning annotations (up to 20 per side) and a JSON report kept
for 30 days. The default project list is the parity-qualified set: packages/types,
packages/utils, packages/supabase, packages/internal-api, apps/tasks and
apps/calendar. CI builds the workspace declarations first, exactly like the
required type-check, so CI parity is the authoritative evidence. Pull requests run
the job only when the shadow tooling changes; workflow_dispatch runs it on demand.
TSRS_PROJECTS, even when one
workspace has both qualified and unqualified configs. Tsc still checks every
project. Exact diagnostic-key multiset differences are printed as advisory
tsrs-only / tsc-only output, including when tsc passes; a shadow mismatch
never changes the authoritative tsc result.
Promotion criteria
Do not replacetsc as the required gate until all of these hold:
- Version alignment. The pinned tsrs release tracks the same TypeScript
minor as the repository gate (or the repository adopts the matching stable
TypeScript minor), and is a non-
devrelease pinned exactly through the owning workspace’s package manager with a reviewed lockfile change. - Parity over time. At least 30 consecutive shadow runs on main per promoted project show location parity, matching success/failure status and no tsrs crash, with warm declarations. Message-text differences are reviewed and recorded. Each promoted project must also have a seeded-error corpus that both checkers reject, covering real type errors, path/ambient declarations and reference boundaries. Until then, keep tsc confirmation on passes too.
- Feature coverage. Every project the required job checks is covered,
including project references (
apps/meet), worker/boundary configs and declaration-emitting builds, or an explicittscfallback is kept for each unsupported feature. - Operational evidence. Linux CI wall time and memory are recorded for the
promoted set, and rollback is a single-commit switch back to
tsc.
scripts/ci/tsrs-shadow.js
and the pre-push gate together.