TypeScript 6.0 is a bridge release, not "ship native TS 7 tomorrow." What a 6.0-era release is for, what to change now, and what to leave alone until a native compiler is actually your default.
Exact GA day for 6.0 can still move; treat this as late-2025 bridge judgment, not a release-notes recitation.
What "bridge" means here
A bridge release exists so teams can:
- Adopt new defaults while the classic
tscpipeline still owns CI. - Surface deprecations with a runway, not as overnight red builds.
- Inventory flags and plugins that will not survive the next major jump.
It is not permission to rewrite the monorepo around preview compilers, claim tsgo is production-default, or present TypeScript 7 as the toolchain you run today. Preview curiosity belongs on a side branch and a later calendar slot.
jsonc// apps/web/tsconfig.json, illustrative bridge posture { "extends": "../../tsconfig.base.json", "compilerOptions": { // Keep strictness you already earned in March; do not loosen for a bump. "strict": true, "noUncheckedIndexedAccess": true, // Pin intentionally; document why if you diverge from the workspace pin. "skipLibCheck": true, }, }
Bump the version. Keep the strictness contract. The bridge fails when the bump PR also "cleans up" half the type debt under cover of a major.
Prep checklist before you bump
I walk @acme workspaces in this order:
- Inventory
compilerOptionsdrift across packages. Copied tsconfigs are the same class of bug as copied.eslintrcfiles from February. - List deprecated flags / APIs you still rely on. Prefer a ticket per sticky option over a silent delete in the bump PR.
- Check custom transformers and
tsc-adjacent plugins. Anything that patches the program AST needs an owner and a "still supported?" answer. - Confirm CI uses the same TypeScript developers install, dual versions are how "green locally, red on main" returns.
- Decide the PR shape: version pin + release-note triage first; behavior
fixes second. Do not mix a mass
anypurge into the bump.
ts// scripts/assert-ts-version.ts, illustrative guard import { version } from 'typescript'; const expected = process.env.EXPECTED_TS ?? '6.0.0'; if (!version.startsWith(expected.split('.').slice(0, 2).join('.'))) { throw new Error(`Expected TypeScript ~${expected}, got ${version}`); }
Cheap guard. Catches the "one package resolved an older typescript" failure mode before review busywork starts.
Defaults: adopt, defer, or refuse
| Change class | Prefer | Why |
|---|---|---|
Stricter default that matches existing strict intent | Adopt in the bump | You already paid for strict; align with upstream |
| Cosmetic emit / module edge case with no product risk | Defer | Noise without signal |
| Flag removal that breaks a generator or legacy package | Refuse until owned | Bridge is runway, not cliff |
| Preview compiler as CI default | Refuse | Wrong decade for this post’s framing |
If you cannot classify a changelog item into one of those four, you are not ready to bump, you are ready to read the notes again.
What not to do in November 2025
- Present-tense "we run tsgo in CI." Preview is not default. Keep demos
labeled preview; keep
tscas the contract until a later wave earns the cutover with real dates. - Loosen
strictto make the bump green. That trades a week of triage for a year of weaker boundaries, the opposite of the brands post’s edge discipline. - Big-bang rewrite of path aliases + module resolution + JSX settings in the same PR as the version bump. Separable concerns; same lesson as Biome PR separation in the Biome migration post.
- Invented speedups. If you want a number, paste wall-clock from your runners before and after. Do not borrow a keynote slide.
Monorepo pin discipline
In a pnpm workspace I want one TypeScript version at the root (or a documented
exception list). Package-level typescript ranges that float independently are
how the bridge becomes five bridges.
json// package.json, illustrative workspace pin { "devDependencies": { "typescript": "~6.0.0" }, "pnpm": { "overrides": { "typescript": "$typescript" } } }
Overrides are blunt; use them when transitive tools drag an older tsc into
PATH. Document the override next to the bridge ADR so future-you knows why it
exists.
Failure modes
Bridge as marketing. Calling every major a "bridge" without a deprecation inventory is marketing without a migration plan.
Preview leakage. One enthusiastic engineer adds a native-compiler script to
package.json "just to try"; six months later half the team thinks it is
supported. Keep experiments in scratch/ or a clearly named optional script.
Silent flag deletion. Removing a deprecated option without a linked ticket hides product risk inside a toolchain PR, reviewers stop reading.
Timeline freelancing. This series parks TS 7 / tsgo-as-default for 2026 slots after real beta/RC dates. Do not smuggle that future into a Nov 2025 post.
Continuity
The TypeScript thread runs from the March leap and strict config through generics and conditionals, branded types, and this 6.0 bridge. Lint arc paused after Biome migration lessons; oxlint waits for a later slot. Playwright page objects pick up the E2E half of the testing thread that Vitest posts started.
Takeaway
Treat TypeScript 6 as a bridge: adopt defaults you already meant, schedule deprecations with owners, and refuse to pretend preview compilers are today’s CI contract.