react-brain
Browse decisions
React & language foundations 3App architecture 9UI 12Platform & native 9Build, test, observe, secure 6AI in React apps 3stack composerdecision recordscensusstaleness bencharchitecturechangelogmethodologyroadmap

entriesreact-foundations · verified 2026-07-13 · react + react-native

TypeScript rigor & public API typing

reviewedconfidence: mediumthis tier holds 50% on the public scorecard (3/19 graded · 0 overturned) →

re-verified 3× — 2026-07-13 · 2026-07-10 · 2026-07-06 · changelog

recommendation

Run strict TypeScript (strict:true, the TS 6 default) and export a small, deliberate public type surface from libraries.

  • library/package author → minimize + version the exported types; avoid leaking internals
  • large repo with slow tsc → TS 7 (Go) is STABLE (~10x); migrate via the TS 6 bridge, following the VS Code pattern in reading
  • not at Meta → use TypeScript, not Flow

Options & tradeoffs

the field considered — and why each one isn’t the default here

optiontradeoffevidence
strict mode tiersstrict vs gradual adoption; TS 6.0 makes strict:true the default
exported type surfacewhat a library/package should export
TypeScript 7 (native/Go)Go rewrite of tsc — 7.0 STABLE (7.0.2, 2026-07-08, verified vs npm): ~10x faster, up to 16x type-checking with parallelization, removes long-deprecated flags; TS 6.0 is the JS-based 'bridge' release to migrate through226.1M/wk · ships in 28/34
Flow (2026)Meta's type checker; syntax converged with TS, compiler ported to Rust; mostly Meta-internal now

evidence: npm weekly downloads (signals snapshot) · “ships in n/D” = adoption across the production-app census, honest denominators

Migration lines

version and deprecation lines this decision tracks — for YOUR repo's sequenced plan: the doctor or npx -y @heart-it/react-brain migrate .

typescript < 7.0.0 → TypeScript 7 (Go-native tsc) via the TS 6 bridge [upgrade · effort M]

TS 7.0 is STABLE (~10x, up to 16x type-checking with parallelization); migrate incrementally — TS 6 as the low-churn bridge, TS 6 and 7 side-by-side in CI, then TS 7 as default (the VS Code ~50-extension migration pattern; their blocker was formatter diffs, not type errors)

registry.npmjs.org/typescript/latest · code.visualstudio.com/blogs/2026/06/26/iterating-faster-…

npm weekly downloads (from the corpus's last signals run): typescript 226.1M

Verified notes

TypeScript 7.0 (the Go/native rewrite of tsc) is STABLE — npm latest = 7.0.2, published 2026-07-08 (verified vs the npm registry; RC was 2026-06-18, stable landed on schedule). ~10x vs TS 6.0, up to 16x type-checking with parallelization. Migrate incrementally through TS 6 (the bridge release) per the VS Code case study in reading.

Canonical reading

Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.

Why does tsgo use so much memory?Zackary Radisic

A heap-level investigation of the Go TypeScript compiler — per-thread Checker duplication, never-freed types, symbol duplication, AST at 45% of heap, plus a fix. A durable deep-dive on TS7/tsgo internals and its concurrency model's cost.

TypeScript Performance in TanStack Table V9Kevin Van Cott (TanStack)

Concrete techniques to cut type-instantiation cost 62-86% (feature maps, materialized interfaces, in/out variance annotations, explicit type args), with measurements. The reference for heavy-generics library authors.

Iterating Faster with TypeScript 7VS Code team (Microsoft)

The production adoption case the tsgo-internals piece lacks: VS Code's ~50-extension codebase cut type-checking 36s→5s (~7x) and editor project-load 60s→10s by migrating INCREMENTALLY — TS 6.0 as a low-churn bridge, then TS 6-and-7 side-by-side in CI (TS 6 still emitting), then esbuild + TS 7 as the default. The surprising blocker wasn't type errors but formatter differences failing pre-commit checks. Evidence that TS 7 (Go-native tsc) is trustworthy for daily use on a large real codebase — if you bridge through TS 6 first.

Sources

Depth (in-domain rules) is owned by the engineering-principles skill — this entry is selection breadth.

The full explanation

The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.

About TypeScript rigor & public API typing

Diataxis: Explanation. This page builds understanding of how much TypeScript strictness to buy and where — the reasoning behind the picks. It is not a tsconfig how-to or a migration runbook. API-design and module-boundary depth is owned by engineering-principles; the CI typecheck gate by RB-E-DX; emit and bundling by RB-E-BUILD. Read this for the why.

The one principle that organises everything: strictness is a boundary discipline

The checker earns its keep where data crosses a boundary — and that's exactly where teams tend to switch it off. The entry's own smell detector says it plainly: explicit any showing up across many files means "the checker is off exactly where bugs concentrate — prefer unknown + narrowing at boundaries." The same principle flips outward for library authors: the exported type surface is itself a boundary — something to minimize and version deliberately, not a side effect of whatever happens to be exported. Strictness inside, a small deliberate surface outside: one discipline, two directions.

The default, and why

Run strict TypeScript (strict:true, the TS 6 default) and export a small, deliberate public type surface from libraries.

strict:true stopped being a stance and became the baseline: TS 6.0 makes it the default, so running loose is now an opt-out you have to justify, not a starting point. The "strict vs gradual adoption" tradeoff still exists for legacy code, but the destination is fixed. And the library half of the default is the boundary principle applied to your consumers: if you're a library/package author, minimize and version the exported types, and avoid leaking internals — your .d.ts is a public API with all the compatibility obligations that implies.

The landscape, and when each piece earns its place

Strict mode tiers — the strict-vs-gradual adoption axis. With strict:true as the TS 6 default, "tiers" is about how an existing codebase gets there, not whether to go.

Exported type surface — what a library/package should export. Minimal, versioned, no leaked internals. For heavy-generics libraries, the TanStack Table V9 work is the reference: concrete techniques (feature maps, materialized interfaces, in/out variance annotations, explicit type args) cut type-instantiation cost 62–86%, with measurements.

TypeScript 7 (native/Go) — the Go rewrite of tsc. 7.0 is STABLE: npm latest is 7.0.2, published 2026-07-08 (verified against the npm registry; the RC was 2026-06-18, and stable landed on schedule). ~10x faster than TS 6.0, up to 16x on type-checking with parallelization, and it removes long-deprecated flags. Earns its place the moment a large repo has a slow tsc.

TypeScript 6.0 (the bridge) — the JS-based release you migrate through, not to. The VS Code case study is the pattern: their ~50-extension codebase cut type-checking 36s→5s (~7x) and editor project-load 60s→10s by going incrementally — TS 6.0 as a low-churn bridge, then TS 6 and 7 side-by-side in CI (TS 6 still emitting), then esbuild + TS 7 as the default.

Flow (2026) — Meta's type checker. Syntax has converged with TS and the compiler was ported to Rust, but it's mostly Meta-internal now. The when-clause is one line: not at Meta → use TypeScript, not Flow.

Tradeoffs and failure modes to name out loud

  • any at the boundary. The entry flags explicit any in 10+ files as a repo-level smell: it turns the checker off exactly where bugs concentrate. unknown + narrowing is the strict-era replacement.
  • A leaky exported surface. Exporting whatever's convenient makes internals part of your public API; the when-clause for library authors is minimize + version, avoid leaking internals.
  • Generics-heavy types that melt the checker. Type-instantiation cost is real and measurable — TanStack Table V9's 62–86% reductions show it's also fixable, with named techniques.
  • Big-bang TS 7 migration. The VS Code evidence says bridge through TS 6 and run 6-and-7 side-by-side in CI first. Their surprising blocker wasn't type errors at all — it was formatter differences failing pre-commit checks.
  • Deprecated-flag debt. TS 7 removes long-deprecated flags — the TS 6 bridge exists to flush those out of your config first.
  • The native compiler's memory bill. The tsgo heap investigation documents the concurrency model's cost — per-thread Checker duplication, never-freed types, symbol duplication, AST at 45% of heap (plus a fix). Speed came from parallelism, and parallelism has a footprint.

How it interacts with the rest of the stack

  • DX (RB-E-DX). Typecheck is one of the invariants CI must gate — an ungated strict:true is a suggestion. Fittingly, VS Code's TS 7 blocker lived in this loop too: formatter diffs failing pre-commit checks, not type errors.
  • Build (RB-E-BUILD). The migration pattern separates checking from emitting: TS 6 kept emitting while TS 7 checked side-by-side, and the end state was esbuild + TS 7 as the default.
  • API/boundary depth (engineering-principles). What a package should export, how boundaries are drawn, and dependency direction are owned there; this entry supplies the type-level rule — small, versioned, deliberate.
  • Upgrades. react-brain migrate flags any typescript below 7.0.0: upgrade via the TS 6 bridge, effort M, following the VS Code pattern above.

In one paragraph

TypeScript rigor is a boundary discipline: run strict:true (the TS 6 default) so the checker is on where data crosses edges — any in bulk means it's off exactly where bugs concentrate, so prefer unknown + narrowing — and, as a library author, treat the exported type surface as a boundary too: small, versioned, no leaked internals. Meanwhile the compiler changed engines: TS 7 (Go-native tsc) is stable — 7.0.2 on npm as of 2026-07-08, ~10x faster, up to 16x type-checking with parallelization — and the proven adoption path is incremental: TS 6.0 as the low-churn bridge, 6 and 7 side-by-side in CI, then TS 7 as default, the way VS Code cut type-checking 36s→5s. Not at Meta? TypeScript, not Flow.


See also: RB-E-DX (CI gates typecheck), RB-E-BUILD (emit vs check — esbuild + TS 7 end state). API and boundary depth: the engineering-principles skill.

Related in react-foundations: react-core · rn-versions