TypeScript 6.0 Migration: What Actually Breaks in Next.js/Supabase
TypeScript

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.

11 min read
TypeScript 6.0 Migration: What Actually Breaks in Next.js/Supabase

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.json never explicitly set "strict": false, you're now opted into strictNullChecks, noImplicitAny, and the rest of the bundle, even if you never asked for it.
  • target: "es5" is deprecated (ES2015 is now the effective floor), and moduleResolution: "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:

json
{
  "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.

Frequently Asked Questions

|

Have more questions? Contact us

Written by

Mahdi Br
Mahdi Br

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote

One email a month — no fluff

RLS gotchas, Next.js cache debugging, and the one Supabase setting that bit me last month.