Imported from docs/adr/0004-typescript-version.md in the go-bananas repository. --- # ADR 0004: TypeScript 6.0.3 rather than 7.x - **Status:** accepted - **Date:** 2026-10-04 - **Revisit when:** typescript-eslint ships TypeScript 7 support ## Context The brief was to take the latest version of everything. For TypeScript, the latest release is 7.0.2, which is the native Go port of the compiler (`tsgo`). ## Decision Pin TypeScript to 6.0.3 in both `web/` and `sdk/`. ## Rationale TypeScript 7.0.2 ships `tsc.js` and a version module. It does **not** ship a JavaScript compiler API: ```console $ npm install typescript@7.0.2 $ node -e "const ts=require('typescript'); console.log(typeof ts.createProgram)" undefined ``` That API is what every type-aware linting tool consumes. `typescript-eslint@8.71.0`, the current release, declares: ``` peerDependencies: { typescript: ">=4.8.4 <6.1.0" } ``` So TypeScript 7 fails to install at all alongside the standard linting stack, and would fail at run time if forced past the peer check. The choice is therefore between: - **TypeScript 7.x** — a much faster compiler, and no type-aware ESLint rules at all, because the tooling that provides them cannot run. `npm install` fails outright without `--legacy-peer-deps`, which is a smell in a project rather than a solution. - **TypeScript 6.0.3** — the newest release that ships both the CLI and the JavaScript API, satisfying every tool in the toolchain. ## Why not upgrade anyway and lose the linting The project's standards require type-aware linting: `@typescript-eslint` rules that need the compiler's type information, which is what catches the mistakes that matter in a codebase using `unknown` at API boundaries. Dropping it to gain compiler speed is a bad trade: the speed is a developer-experience improvement, and the linting is a correctness control. ## What this costs TypeScript 6.0.3 is slower than 7.0.2. On this codebase the typecheck completes in well under a second, so the difference is not observable, and the compilation cost that matters is Vite's, which uses its own transform. ## When to revisit When typescript-eslint declares support for TypeScript 7, which requires the JavaScript API or a native alternative to it. That is a one-line version bump plus a `make check` run. This ADR exists so that the pin is a decision with a reason rather than an accident that outlives its justification. ## A related note: `baseUrl` is deprecated TypeScript 6 deprecates `compilerOptions.baseUrl`. The project resolves `paths` relative to the tsconfig instead, which is the documented replacement and removes a compiler option that only ever existed to make `paths` work.