Skip to content
Nicolas Chiong· 5 min read

A TypeScript 7 config cleanup gate

TypeScript 7 is fast enough to change daily feedback loops. The safer migration starts with TypeScript 6 config cleanup, not a blind compiler swap.

TypeScript 7 is the rare tooling release where the headline number matters. Microsoft published full-build speedups around 8x to 12x on large projects, with VS Code moving from 125.7 seconds on TypeScript 6 to 10.6 seconds on TypeScript 7. That is not just a nicer CI chart. It changes whether local type-checking feels cheap enough to run before every handoff, including agent handoffs.

Format: migration gate

I would not make TypeScript 7 a normal dependency bump in a production repo. The lazy path is a gate: first make the project boring on TypeScript 6, then trial TypeScript 7 where the ecosystem does not still need the old compiler API.

That distinction matters because TypeScript 7.0 is a native Go port with the normal tsc command, but it does not ship the stable programmatic API many tools still import from typescript. The release notes call out a side-by-side path with @typescript/typescript6 for utilities that still need the TypeScript 6 API.

So my migration question is not "does TypeScript 7 work?" It is "can this repo explain every TypeScript 6 deprecation before TypeScript 7 turns it into a harder failure?"

Gate 1: compile cleanly on TypeScript 6 without hiding deprecations

Start with TypeScript 6 because TypeScript 7 intentionally adopts its defaults and hardens several deprecations. A project that only passes because ignoreDeprecations is masking config debt is not ready.

The first check is boring:

npx tsc -p tsconfig.json --noEmit
npx tsc -p tsconfig.json --noEmit --stableTypeOrdering

The second command is not meant to become a permanent CI mode. TypeScript documents --stableTypeOrdering as a 6-to-7 diagnostic helper, and warns it can slow type-checking by up to 25 percent depending on the codebase. That is fine for a temporary gate. If stable ordering exposes a new type error, I would rather fix the inference now than discover it after a compiler swap.

This is also where I would link the work to the broader build-tool story. If the repo already has a React build migration in flight, use that checklist as context rather than inventing a parallel tooling program. I wrote about this in the Vite and Turbopack comparison, and the same rule applies here: measure the build boundary that developers actually hit.

Gate 2: make implicit globals explicit

The TypeScript 6 and 7 default change I expect to surprise teams is types. TypeScript 7 says types now defaults to an empty array, and the old behavior can be restored with types: ["*"]. That old behavior was convenient, but it also meant a workspace could silently depend on whichever @types packages happened to be present.

I would not restore the old behavior unless the repo is blocked and needs a short-lived escape hatch. The cleaner fix is to list what the project actually uses:

{
  "compilerOptions": {
    "types": ["node", "vitest"]
  }
}

This catches messy test and runtime boundaries. Browser packages should not inherit Node globals by accident. Node packages should not get test globals because one workspace dependency pulled them into node_modules. If a package needs jest, vitest, node, or bun, say so in that package's tsconfig.

Gate 3: choose modern module resolution on purpose

The next cleanup is module resolution. TypeScript 6 deprecates moduleResolution: node or node10; TypeScript 7 lists them as unsupported, with nodenext and bundler as the realistic choices.

My default split is simple:

Project shapePrefer
Bundled web appmoduleResolution: "bundler"
Node app or package run by NodemoduleResolution: "nodenext"
Library with dual packagingtest both emitted package entrypoints

This is where a migration can accidentally become a packaging rewrite. Avoid that. Change one package, run its type-check, run the smallest import smoke test, then repeat. If package exports are already fragile, TypeScript 7 is not the root cause. It is just the first tool loud enough to expose the ambiguity.

Gate 4: check rootDir, baseUrl, and import attributes

TypeScript 7 calls out rootDir and types as the two surprisingly visible default changes. If a monorepo keeps tsconfig.json above src, set rootDir explicitly before changing compilers. Otherwise emitted declaration paths can move in ways that look like a compiler regression.

I would also remove baseUrl as a migration step instead of carrying it forward. TypeScript 7 no longer supports it, and TypeScript 6 points projects toward paths relative to the project root. That is a mechanical cleanup with real payoff: fewer resolution rules to explain in code review.

Finally, search for import assertions:

rg "asserts \{ type:" --glob '*.{ts,tsx,js,jsx,mts,cts}'

The old asserts import syntax has moved to with. This is the kind of change that is cheap to fix once and noisy to debug later.

Gate 5: run TypeScript 7 where tools do not embed TypeScript

TypeScript 7.0 is production-oriented, but the release notes are explicit that embedded-language workflows can still need TypeScript 6. Vue, MDX, Astro, Svelte, Angular template checking, and language-service-plugin-heavy setups may not get the full TypeScript 7 path immediately because 7.0 does not yet expose the stable programmatic API.

That means I would split adoption into lanes:

  1. CI type-check for plain TypeScript packages.
  2. Editor trial for developers who do not need language service plugins.
  3. Side-by-side TypeScript 6 for tools that import the compiler API.
  4. Framework-specific adoption only after the framework confirms support.

The side-by-side package exists for exactly this awkward middle period. Use it. Do not block fast tsc for every package because one lint rule or template compiler still needs the TypeScript 6 API.

What I would measure

I would capture four numbers before and after: cold tsc --noEmit, incremental or --build time, editor time to first diagnostic, and peak memory on CI. The TypeScript team reports big wins, but the only number that changes your delivery habit is the one from your own repo.

For Node-heavy codebases, I would pair this with the runtime checks from the Node 26.5 text imports and streams checklist. Compiler speed is useful, but runtime contracts still need their own proof.

The forward-looking move is not to celebrate a faster compiler. It is to spend the saved seconds on checks people previously skipped: local type-checks before agent handoff, smaller CI batches, and editor diagnostics that arrive while the code is still in your head.

typescriptcompilerjavascriptbuild-tools

References

  1. devblogs.microsoft.comTypeScript team
  2. typescriptlang.orgTypeScript handbook
  3. devblogs.microsoft.comDaniel Rosenwasser
  4. github.commicrosoft/typescript-go

Related writing

Let's make something useful.

Start a conversation