AniUI Academy

Upgrading to TypeScript 6 and 7

The two-step upgrade: TS 6 is the deprecation-warning release that readies your code, TS 7 is where the native compiler ships. What to fix, in what order.

10 min read

Most TypeScript upgrades through the course of this track have been point releases: bump the package, run the tests, done. The jump through TypeScript 6 and TypeScript 7 is different enough to be worth a lesson, mostly because the sensible path is two small upgrades instead of one big one. This lesson is about why that is, and what to actually do under each step.

The two-step migration, and why it exists

The direction the TypeScript team has set is:

  • TypeScript 6 is a transition release. It adds compile-time warnings for the patterns TS 7 removes or changes, but it still compiles the old code and still behaves the way TS 5 did at runtime. You can ship a TS 6 build to production on the same day you upgrade; the warnings tell you what to fix on your own schedule.
  • TypeScript 7 is where the warnings become errors and where the native compiler covered in the previous lesson becomes the default. By the time you move from TS 6 to TS 7, the list of things that "stop working" should be empty, because you already fixed them in the TS 6 window.

Going straight from TS 5 to TS 7 is legal. It is, in practice, more painful: every deprecation that TS 6 would have warned you about now appears as a hard error in a single PR, mixed in with any genuine tooling-compatibility issue from the native-compiler cutover. The recommended path is to do those two things in two different pull requests, one after the other, each small enough to review and revert cleanly.

TS 6, in practice

The shape of a TS 6 upgrade PR tends to look like this:

npm install --save-dev typescript@6
npx tsc --noEmit

The build keeps working; the type-check now reports a batch of new warnings. They're almost all in one of three families:

  • Implicit any the compiler used to accept silently. A couple of older inference paths that previously gave up and returned any without a noImplicitAny error are tightened in TS 6. The fix is the same one this track has been teaching: annotate the parameter, or type the intermediate value as unknown and narrow it with a type guard. If a real any is needed in one specific place, writing it explicitly (: any) is the honest answer — it's deliberate and a reader can see the intent.
  • Deprecated type-system syntax. A small set of older constructs that the team has repeatedly flagged (certain enum patterns, a couple of utility-type aliases kept around for backwards compatibility) start warning. The TS release notes list each one with its modern replacement. Most codebases have very few of them.
  • Config options whose default is changing. A handful of tsconfig.json options whose default value becomes the opposite under TS 7 start warning in TS 6 if you're still relying on the old default. The fix is to set the option explicitly in tsconfig.json — which is also the kind of thing you want set explicitly anyway, since a config option that depends on which version of the compiler is installed is a subtle source of drift across machines.

The practical work is: ship TS 6, watch the CI type-check for the warnings, fix them over a sprint or two, and only then open the TS 7 PR.

TS 7, in practice

With a clean TS 6 build (no warnings left), the TS 7 upgrade is mostly a package bump plus a few compatibility checks:

npm install --save-dev typescript@7
npx tsc --noEmit

Three categories of thing to verify once:

  • Custom tooling that depends on compiler internals. This is the one real footgun. Any package in your tree that uses the TypeScript compiler's non-public API (ts-morph, custom transformers, some code-generation tools, a few bundler plugins) needs to be on a release that was published against the TS 7 internals. The error message when this is broken is usually along the lines of "cannot find ts.Diagnostics.*" or "function expected 2 arguments, got 3." The fix is to update that tool to a TS 7-compatible version, or — if you maintain it — to switch it off the internals and onto the stable public compiler API.
  • CI caches. A build cache keyed on the TypeScript version will be invalidated on the first TS 7 run. Expect one slow CI pass and then the steady-state speedup from the native compiler.
  • The small set of inference-edge-case changes. TS 7 removes a couple of inconsistent behaviours the old compiler had — places where the TypeScript spec said one thing but the implementation historically did another. If any of your code was relying on the old implementation-specific behaviour, the fix is usually one line. These are called out in the TS 7 release notes individually.

Nothing in that list is architectural. It's the normal kind of breaking-change checklist a major version ships, with the native compiler as the payoff.

Checking a dependency before upgrading

A third-party package's peerDependencies: { typescript: ">=5" } is information, not a guarantee that the package has actually been tested against TS 7. The honest check is:

  • Does the package's README or release notes mention TS 7 support?
  • Does its CI matrix list TS 7?
  • Has a recent release updated its own TypeScript-dependent code?

If the answer to all three is no, the realistic options are the ones the New Architecture lesson named for React Native: pin briefly, PR the maintainer, or swap the dependency. "Hope and upgrade" is not one of them — the failure mode is subtle type drift that a build smoke test won't catch.

For your own libraries that you ship with types, the symmetric work is: add a TS 7 entry to your CI matrix during the TS 6 window, and cut a release that says it was tested against both before TS 7 lands as the default for your consumers.

The honest reason for all of this

It would be shorter to say "just upgrade" — but shorter isn't always right. The two-step exists because the TypeScript team wanted the scariest part of the rewrite (the native compiler) to land in a world where the type-level compatibility questions were already answered. If you follow the two-step, you get the native compiler as pure upside and the deprecations as background work. If you don't, you get both costs in the same PR and no obvious way to tell which change caused which failure. This lesson exists to let you make that choice deliberately, not by accident.

What to remember

  • The recommended upgrade path is TS 5 → TS 6 → TS 7, not a direct jump. TS 6 is the deprecation-warning release; TS 7 enforces the same patterns as errors and ships the native compiler.
  • Under TS 6, fix the new warnings on your own schedule: mostly implicit any, a few deprecated syntax forms, and a handful of config defaults you should set explicitly anyway.
  • Under TS 7, the main compatibility work is for custom tooling that depended on the compiler's internal, non-public APIs. The public API surface is stable.
  • Peer-dependency ranges on third-party packages are not proof that the package has been tested against TS 7. Check the README, release notes and CI matrix before relying on it.
  • The two-step exists specifically so that the type-system questions and the native-compiler cutover land in two separate, reviewable PRs instead of one big one.

Check yourself

4 questions · pass 3/4 to unlock Migrating JavaScript to TypeScript

up to 50
  1. 1.Why is the recommended path for most teams 'TS 5 → TS 6 → TS 7' rather than jumping straight from TS 5 to TS 7?

  2. 2.A library you depend on has peerDependencies: { typescript: '>=5' } and you want to upgrade your app to TS 7. What's the realistic check before upgrading?

  3. 3.TS 6 starts warning that a specific any-returning pattern in your codebase will become an error in TS 7. What is the smallest, safest fix to retire the warning?

  4. 4.After upgrading to TS 7, your CI type-check step is much faster — but one package's build now fails in a way it didn't on TS 6. The error cites 'cannot find internal module ts.Diagnostics.*'. What is this almost certainly telling you?

4 left to answer

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.