ADR-0019: Pin TypeScript 6 to keep type-aware linting
ADR-0019: Pin TypeScript 6 to keep type-aware linting
- Status: Accepted
- Date: 2026-07-30
- Supersedes: —
- Superseded by: —
Context
Scaffolding the monorepo (WI-002) required choosing a TypeScript version, and the obvious answer turned out to be blocked.
Verified against the npm registry on 30 July 2026:
| Package | Version | Constraint |
|---|---|---|
typescript | 7.0.2 latest, 6.0.3 latest 6.x | — |
typescript-eslint | 8.65.0 latest, 8.65.1-alpha.17 canary | typescript: ">=4.8.4 <6.1.0" |
Both the latest and the canary tag of typescript-eslint exclude TypeScript 7. TypeScript 7 is the Go-based compiler rewrite, and the surrounding tooling ecosystem has not caught up.
So the fork is: latest compiler, or type-aware linting. Not both.
Decision
Pin TypeScript 6.0.3 across the monorepo, through packages/config and a single root devDependency.
Rationale
The type-aware typescript-eslint rules are the ones that catch real defects rather than style nits — no-floating-promises, no-misused-promises, no-unsafe-argument. This project is asynchronous Workers code throughout, where an unawaited promise is a silent failure rather than a lint annoyance. Trading those rules for compile speed is the wrong call on a codebase that agents will be writing at volume.
The ecosystem risk points the same way. typescript-eslint excluding TS 7 even on its canary tag is a signal rather than an oversight: Drizzle, Astro, Hono and Expo are all far more likely to be tested against 6.x today. Debugging another project’s TS 7 incompatibility is not work this project should be doing.
Compile speed matters least of the three. Turborepo caching means a warm typecheck is a cache hit, not a compile.
Consequences
- One minor version behind latest, and slower cold compiles than TS 7 would give.
tsconfig.base.jsoncannot use TypeScript 7-only options.- This is a temporary pin, not a permanent position. Revisit it as soon as
typescript-eslintships TS 7 support — the trigger is that package’s peer range, not a calendar date. - Every package inherits the version through
packages/config, so upgrading is a one-line change plus a gate run rather than a sweep. - CI pins the same version, so a local/CI TypeScript mismatch cannot appear silently.
Alternatives considered
TypeScript 7.0.2 with non-type-aware ESLint. Latest compiler, meaningfully faster. Rejected: it trades away the lint rules that catch async bugs, on a codebase that is almost entirely async, and adds unquantified risk across four other stack components.
TypeScript 7.0.2, deferring the lint decision. Keeps momentum. Rejected: it leaves the gate weaker than docs/standards/ci-and-gates.md describes for an unbounded period, and deferring is how a temporary gap becomes permanent.