ADR-0007: TypeScript 7, and TypeScript 6 only where a tool needs its API¶
Status: Accepted Date: 2026-10-12 Deciders: Alex Nodeland
Context¶
lattice RFC-0002 chose TypeScript 7 for type checking, and asked phase 1 to confirm each tool. TypeScript 7 is the native compiler, and its package has no programmatic API at its main entry until 7.1; tools that load typescript as a library would need TypeScript 6 under an alias. RFC-0002 expected two: openapi-typescript and knip.
Phase 1 checked every tool the RFC names, on 2026-10-12:
| Tool | Version | Loads typescript? |
Under TypeScript 7 |
|---|---|---|---|
typescript |
7.0.2 | tsc type-checks the web packages. Its main entry exports only version and versionMajorMinor; the API is under typescript/unstable/* |
|
| knip | 6.41.0 | No: it parses with oxc, and depends on no typescript |
Works |
openapi-typescript |
7.13.0 | Yes: a peer dependency on typescript@^5.x, and ts.factory at import |
Fails at import: Cannot read properties of undefined (reading 'createKeywordTypeNode') |
Vite, @vitejs/plugin-react |
8.3.4, 6.1.2 | No: Vite transforms with oxc | Works |
| Vitest | 5.0.3 | No | Works |
| Biome | 2.5.15 | No: it is native | Works |
json-schema-to-typescript, openapi-fetch |
16.0.0, 0.17.0 | No | Not run; neither depends on typescript |
TanStack Router's plugin, size-limit, playwright-bdd |
1.168.43, 14.2.0, 9.2.1 | No (the router's plugin uses Babel) | Not run; none depends on typescript |
How a tool gets TypeScript 6 matters, because it imports typescript by name:
- An alias under another name at the root, such as
typescript6, reaches no tool. - Bun's nested
overrides("openapi-typescript": {"typescript": ...}) don't apply: under Bun 1.4.3,openapi-typescriptstill loads 7. - TypeScript 6 as the root's
typescript, and 7 under another name, works for the tools, but everytscon the path is then 6. - An alias in the one package that runs the tool works under Bun's isolated installs: a package with
openapi-typescriptand"typescript": "npm:typescript@6.0.3"in its devDependencies generates types with 6, while the root'stscstays 7. In that package, though, a baretscis 6.
Decision¶
- The root's
typescriptis 7.0.2, and every web package'stypecheckruns it. - Phase 1 installs no TypeScript 6. No tool it uses loads
typescript. openapi-typescriptalone needs TypeScript 6, under an alias in the package that runs it. Phase 3 adds both, and settles where generation runs so that the package's owntypecheckstill runs 7.- A tool is checked when it is added, against this table, and the alias goes when the tool supports 7.
Options considered¶
| Option | For | Against |
|---|---|---|
| 7 at the root; 6 aliased only beside the one tool that needs it, when it is added (chosen) | Nothing to carry until a tool needs it. Every tsc but one package's is 7 |
Phase 3 has to keep that package's typecheck on 7 |
6 at the root as typescript, 7 under another name |
Any tool that loads typescript works |
Every bare tsc is 6, and editors pick up 6 |
| 6 under an alias at the root now, as RFC-0002 sketched | Ready for phase 3 | Reaches no tool, since none imports the alias, and knip would report it unused |
Consequences¶
- Easier: type checking is the native compiler's speed, and phase 1 carries one TypeScript.
- Harder: phase 3's generation needs its own package or an explicit path to the root's
tsc. - To revisit: the alias goes when
openapi-typescriptsupports TypeScript 7's API, from 7.1.