TypeScript 7 is easy to describe as a performance release. The compiler and language service have been rewritten in Go, and the TypeScript team reports full-build improvements of roughly 8–12× across several large open-source codebases.

That is useful, but it is not the migration plan.

The more important fact is that TypeScript 7 replaces the compiler implementation, changes several configuration defaults, removes deprecated behavior, introduces parallel work, and does not yet expose a stable programmatic API. I would therefore treat it as a toolchain migration rather than a routine package update.

The goal is not to reproduce someone else’s headline benchmark. It is to make type checking faster without silently changing which files, globals, modules, or downstream tools the build accepts.

Decide whether the project is eligible

The first question is not “Does the code contain TypeScript?” It is “Who calls TypeScript, and how?”

A project that runs tsc --noEmit or tsc -b directly is a strong early candidate. A project whose framework, linter, code generator, or editor plugin imports the typescript package as an API has a different dependency boundary.

TypeScript 7.0 deliberately ships without a programmatic API. The official release announcement recommends keeping TypeScript 6 available for API consumers and says that Vue, MDX, Astro, and Svelte workflows will generally need to remain on TypeScript 6 for now. Angular projects may use 7 for command-line checking while retaining 6 for template-aware editor support.

That distinction applies to this portfolio. Its build uses Vue and vue-tsc, so replacing its compiler dependency merely because 7.0 exists would ignore the current compatibility boundary. Waiting is a migration decision when a tool owns part of the compiler integration.

Before changing a dependency, classify the project:

Project shape Sensible first move
Direct tsc CLI, TypeScript source Trial TypeScript 7 in a separate check
Project references or monorepo Trial 7, then measure CPU and memory as well as time
Tool imports the TypeScript API Keep 6 available side-by-side
Vue, Svelte, Astro, MDX, or template-aware framework Follow the framework integration; do not force the compiler underneath it
JavaScript checked through JSDoc Audit the documented JavaScript behavior changes before trialing 7

The native compiler repository tracks the remaining surface directly: parsing, type checking, emit, watch mode, project references, and incremental builds are implemented, while the API is not ready in 7.0.

Use TypeScript 6 as the compatibility gate

TypeScript 6 exists as a bridge between the old JavaScript compiler and the native one. I would upgrade to 6 first, make that change quiet, and only then evaluate 7.

The useful acceptance condition comes from the TypeScript team: code that compiles under 6 with stableTypeOrdering enabled and without ignoreDeprecations should generally compile the same way under 7.

A transition configuration can make that condition explicit:

{
  "compilerOptions": {
    "stableTypeOrdering": true,
    "strict": true,
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "rootDir": "./src",
    "types": ["node"]
  },
  "include": ["src/**/*.ts"]
}

This is an example, not a universal configuration. A bundled browser application would usually select moduleResolution: "Bundler"; a Node application should model the Node version and module system it actually runs. The important part is that these are product and runtime decisions, not compiler defaults left to drift.

Do not use ignoreDeprecations as the bridge. TypeScript 6 can suppress its warnings with that option, but TypeScript 7 removes the deprecated settings entirely. A green build achieved by hiding the migration work is not evidence of compatibility.

The TypeScript 6 release notes document the full bridge, including the changed defaults and an experimental codemod. I would review the diff produced by any codemod like a hand-written configuration change; tsconfig.json describes runtime assumptions, so mechanical validity is not enough.

Make every changed default intentional

TypeScript 7 adopts the defaults introduced by 6:

  • strict is enabled;
  • module defaults to esnext;
  • target follows the latest stable ECMAScript version before esnext;
  • noUncheckedSideEffectImports is enabled;
  • rootDir defaults to the directory containing tsconfig.json;
  • types defaults to an empty list.

The last two can produce confusing symptoms. An implicit rootDir can move emitted files from dist/index.js to dist/src/index.js. An empty types list can make globals such as process, describe, or expect disappear even though their declaration packages are installed.

I prefer fixing both by describing the project honestly:

{
  "compilerOptions": {
    "rootDir": "./src",
    "types": ["node", "jest"]
  }
}

Using "types": ["*"] restores the older discovery behavior, but it also restores accidental access to every visible @types package. An explicit list makes the global namespace and dependency boundary reviewable.

Path aliases need similar care. baseUrl is no longer supported in 7. Paths are resolved from the configuration file, so the prefix belongs in each mapping:

{
  "compilerOptions": {
    "paths": {
      "@app/*": ["./src/app/*"],
      "@lib/*": ["./src/lib/*"]
    }
  }
}

This change is also a good moment to verify that the runtime or bundler implements the same aliases. TypeScript resolving an import has never guaranteed that Node or a browser can load it.

Other removals deserve an explicit owner. The old node/node10 and classic resolution modes are gone; ES5 output and legacy AMD, UMD, and SystemJS module output are gone; import attributes use with rather than the legacy assert syntax; and esModuleInterop can no longer be disabled. If a project still relies on one of those behaviors, the work is a runtime or packaging migration, not a compiler-flag substitution.

Run both compilers before switching the required check

For tools that still need the old API, the TypeScript team provides @typescript/typescript6. It exposes the 6.0 API and installs a tsc6 executable, allowing the native tsc to live beside it:

{
  "devDependencies": {
    "@typescript/native": "npm:typescript@7.0.2",
    "typescript": "npm:@typescript/typescript6@6.0.2"
  },
  "scripts": {
    "typecheck:6": "tsc6 --noEmit --pretty false",
    "typecheck:7": "tsc --noEmit --pretty false"
  }
}

Pinning exact versions during the evaluation keeps the comparison stable. The normal version policy can resume after the migration is understood.

Run both checks on the same commit and classify every difference:

  1. Configuration difference: the two compilers include different files, globals, libraries, or output paths.
  2. Intentional semantic difference: for example, TypeScript 7 preserves complete Unicode code points when inferring through template literal types.
  3. JavaScript or JSDoc difference: the native implementation intentionally removes several Closure-style and legacy constructor patterns. The project’s CHANGES.md is the authoritative inventory.
  4. Tooling incompatibility: a consumer expects the TypeScript 6 API or protocol.
  5. Possible regression: the behavior is neither documented nor expected and needs a minimal reproduction upstream.

Do not add broad exclusions, skipLibCheck, or new any annotations simply to make the second command green. Those changes destroy the evidence needed to understand whether the new compiler found a real problem.

For libraries, compare more than exit codes. Build both ways and diff the published file list, JavaScript module shape, source maps, and generated declarations. For applications, run the production bundle and test the built artifact under the supported runtime—not only the development server.

Treat parallelism as a capacity decision

TypeScript 7 parallelizes parsing, checking, and emitting. It uses four checker workers by default and adds experimental --checkers, --builders, and --singleThreaded controls.

More workers are not automatically better. Increasing checkers can reduce elapsed time while increasing memory. Project-reference builders multiply the checker count: four builders with four checkers can permit sixteen checker workers. That may help a large workstation and hurt a constrained CI runner sharing CPU with tests, bundling, and service containers.

My default rollout would leave parallelism unchanged, record the baseline, and tune only when the measurements show a reason. Capture at least:

  • elapsed type-check time;
  • peak memory or CI runner pressure;
  • total pipeline time, including neighboring jobs;
  • cold and warm runs;
  • editor time to first diagnostic on a representative workspace.

If environments produce order-dependent diagnostics, fix the checker count while investigating. If the build becomes unstable under resource pressure, reducing concurrency is more useful than celebrating an isolated local speedup.

Define the rollback before rollout

A migration is safer when “go back” is a tested command rather than an emergency edit.

Keep TypeScript 6 as a non-blocking comparison for a short observation window after switching the required check to 7. Retain the package alias and lockfile until editor integrations, CI, production builds, and declaration consumers have all exercised the new path.

Rollback should be triggered by evidence such as:

  • a required framework or plugin cannot use the new language service;
  • declaration or emit differences break consumers;
  • CI memory pressure removes the time saved by compilation;
  • diagnostics vary across equivalent environments;
  • an undocumented compiler difference cannot be isolated or accepted safely.

The version number alone is not a reason to migrate, and a large upstream benchmark is not proof that a specific repository benefits. TypeScript 7 is valuable because it can shorten a feedback loop engineers run all day. The responsible way to claim that value is to preserve the old compiler as a reference, make configuration explicit, respect API-owning tools, and measure the entire delivery path.

That turns a fast compiler into a safer engineering system.