TypeScript 6.0 Migration: What Actually Breaks in Next.js/Supabase
TypeScript 6.0 shipped in March 2026 with strict mode on by default and several legacy options removed. Here is what actually breaks migrating a real Next.js + Supabase codebase, in the order to fix it.
TypeScript 6.0 shipped on March 23, 2026, and it's the last version of the compiler written in JavaScript before the team's full-speed move to the Go-based TypeScript 7 (tsgo). Because of that, 6.0 is a genuine "spring cleaning" release: several long-deprecated options are gone, strict mode is on by default, and legacy targets are removed outright rather than just discouraged.
Most of the writeups floating around right now are abstract changelogs. This is what those changes actually do to a real Next.js App Router + Supabase project — the errors you'll see, and the order that minimizes wasted work.
What actually changed#
- Strict mode is on by default. If your
tsconfig.jsonnever explicitly set"strict": false, you're now opted intostrictNullChecks,noImplicitAny, and the rest of the bundle, even if you never asked for it. target: "es5"is deprecated (ES2015 is now the effective floor), andmoduleResolution: "classic"is removed entirely. You must use"node16","nodenext", or"bundler"(the one Next.js projects almost always want). Per the official TypeScript 6.0 release notes, deprecated options still compile in 6.0 (silence the warning with"ignoreDeprecations": "6.0"if you need breathing room) but are slated for hard removal in TypeScript 7.0 — treat the deprecation warning as a deadline, not background noise.module: "amd" | "umd" | "systemjs" | "none"are deprecated, not yet hard errors. These predate the ESM ecosystem and have no place in an App Router project, but you may have inherited one from a dependency's shared tsconfig — fix it now rather than waiting for TypeScript 7.0 to force the issue.- All code is now assumed to be in strict-mode JavaScript syntax. If legacy or generated code uses reserved words (
await,static,private,public, etc.) as plain identifiers, that now fails to parse. This mostly affects legacy scripts or generated code, not typical Next.js source.
Fix order for a Next.js + Supabase project#
Trying to fix everything at once produces a wall of hundreds of errors with no sense of progress. This order clears the noisy, mechanical errors first so what's left is the genuine type-safety issues worth your attention.
1. Fix config-level errors first. Run tsc --noEmit and look only at errors that reference tsconfig.json itself — moduleResolution, target, module values. These are one-line fixes and they unblock everything downstream. For a standard Next.js App Router project:
{
"compilerOptions": {
"target": "es2022",
"moduleResolution": "bundler",
"module": "esnext"
}
}2. Fix strictNullChecks errors in your data layer next, specifically anywhere you touch a Supabase client response. Supabase's generated types already model nullability accurately (a .single() query can return null), but code written under lenient mode often accessed .data.someField without a null check because it "worked" at runtime. This is where strict mode earns its keep — and where you'll find the highest-value real bugs, not just noise.
3. Fix noImplicitAny in Server Actions and API route handlers last. These tend to be the highest volume of trivial errors (untyped formData.get() results, untyped request bodies) and the lowest risk — mechanical typing, not logic changes. Doing this last means your context budget goes to the data-layer bugs that matter, not to typing 200 form handlers.
4. Re-run your test suite, not just the type checker. Strict null checks catching a real bug means a code path changes behavior, not just its types — a .single() result that was silently null and got treated as an object might now throw where it used to fail silently downstream. That's the fix working as intended, but it needs a test pass to confirm.
The error you'll hit that isn't really about TypeScript 6.0#
If you see Cannot find module 'X' or its corresponding type declarations appearing for packages that worked fine before, check whether it's actually the moduleResolution change surfacing a package that never shipped proper ESM exports — not a new TypeScript 6.0 bug. See TypeScript: could not find declaration file for module — fix for the general diagnostic steps, which still apply.
When the new errors come from node_modules, not your code#
After the four-step fix order above, you may still see errors whose file path points
into node_modules — a dependency's own .d.ts file failing to type-check under the
compiler you just upgraded to. This isn't a bug in your code, and it isn't necessarily a
bug in the dependency either: every TypeScript minor and major release ships stricter or
different checking in the type-checker itself, and a package that type-checked cleanly
under an older compiler can trip a newer one the moment you point tsc at it.
The default in almost every Next.js starter (create-next-app included) is
"skipLibCheck": true, which tells the compiler to skip type-checking .d.ts files
entirely and only check the types they export, not their internal implementation. If
your tsconfig.json inherited a shared config that turned this off, or a monorepo
package's tsconfig.json doesn't extend the same base config as the app, this is
exactly when it bites: a library upgrade or a compiler upgrade surfaces a .d.ts error
that has nothing to do with anything you wrote, and the fix is turning skipLibCheck
back on for that project rather than trying to patch a dependency's shipped types.
How to force tsc to ignore the node_modules folder
covers the related case where tsc is walking into node_modules at all because of an
include pattern that's broader than intended — a different root cause with the same
symptom of node_modules paths showing up in your error output.
Further reading: TS2564: Why Constructor Methods Don't Count as Init.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
Continue Reading
TS2564: Why Constructor Methods Don't Count as Init
TS2564 fires when a class field is typed but never guaranteed to be set. The fix depends on WHY it's unset: a default value, constructor assignment, the definite-assignment `!`, or an optional `?`. Picking the wrong one hides real bugs.
Fix "Property does not exist on Window" in TypeScript
Learn how to safely extend the Window interface in TypeScript with declaration merging and declare global, and why bracket notation on an undeclared key fails under noImplicitAny.
Fix Vitest: Cannot find namespace vi in TypeScript
Keep mock return values checked against the real function signature, and verify both TypeScript compilation and module mocking at runtime.


