TypeScript in 2026: Install & Configure with Node.js 20+
Install TypeScript 5.4.5+ with npm 9.8+, configure for Node.js 20.x LTS, and resolve Supabase/Next.js type errors — with strict tsconfig.json and Jest/ESLint setup.
TL;DR#
If you run npm install typescript@latest and see Cannot find module '@types/node', Property 'auth' does not exist on type 'SupabaseClient', or ESLint/Prettier break after the upgrade, the root cause is usually a mismatch between your Node.js runtime, TypeScript version, and type declaration packages.
Fix it by upgrading Node.js to 20.x LTS, installing typescript@5.4.5 (or the current stable), @types/node@latest, and upgrading @supabase/supabase-js to the latest version, then setting "module": "esnext" and "moduleResolution": "bundler" in tsconfig.json (the Next.js defaults) along with esModuleInterop: true.
If that doesn’t work, check your engines field in package.json, verify npm ci runs in CI, and ensure ts-jest@29+ is installed for Jest compatibility.
What you'll see#
You run npm install typescript@latest in a fresh or existing project — maybe after seeing "npm typescript latest version" in Google — and npm run build fails with:
src/lib/supabase.ts:3:23 - error TS2307: Cannot find module '@types/node' or its corresponding type declarations.Then, when you try to use Supabase:
const supabase = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!)
const { data, error } = await supabase.auth.getSession()You see:
Property 'auth' does not exist on type 'SupabaseClient<Database, PublicSchemaName>'.It happens when you run npm run dev, npm run build, or deploy to Vercel/GitHub Actions — especially in projects that started on Node.js 16 or 18, or where engines in package.json is outdated. The behavior is the same across macOS, Linux, and Windows.
Root cause#
TypeScript 5.4.5 (released April 2024) requires Node.js >=14.17 — so Node 16, 18, and 20 all satisfy it. npm’s engines field checking is a warning by default (not a hard block), so if you see install failures the cause is something else: a mismatched engines declaration in your own package.json, or a peer-dependency conflict with another tool.
TypeScript 5.4+ tightened module resolution and type inference, and some projects find they need @types/node installed explicitly when they import Node.js APIs (such as Buffer or process). Global DOM types like URL and Event live in lib.dom.d.ts and do not require @types/node.
The Supabase client (@supabase/supabase-js) has shipped several type-definition improvements across versions. If you see Property ‘auth’ does not exist on type ‘SupabaseClient’, the usual cause is an outdated version of the package or a tsconfig that does not match what the library expects — not a TypeScript runtime enforcement change (TypeScript erases all types at build time and adds no runtime checks).
The relevant code path in your project is:
// src/lib/supabase.ts
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
export default supabaseThis fails when @supabase/supabase-js is out of date and the installed type definitions do not match what TypeScript 5.4 resolves.
The fix#
Here’s the minimal, verified sequence that works in production:
- Upgrade Node.js to 20.x LTS (e.g., via
nvm install 20.15.0 && nvm use 20) - Install
typescript@5.4.5(or the current stable),@types/node@latest, and the latest@supabase/supabase-js - Update
tsconfig.jsonto use"module": "esnext","moduleResolution": "bundler",esModuleInterop: true, andskipLibCheck: true(the Next.js create-next-app defaults) - Ensure
enginesinpackage.jsonmatches Node.js 20.x
# Check current Node version
node -v
# If <20.x, upgrade:
nvm install 20.15.0 && nvm use 20.15.0Then:
# Install compatible versions
npm install typescript@5.4.5 @types/node@latest @supabase/supabase-js@latestUpdate tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM"],
"module": "esnext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}That single change addresses the cause because "module": "esnext" + "moduleResolution": "bundler" are the defaults generated by create-next-app and what Next.js’s bundler (webpack/Turbopack) expects — using NodeNext in a Next.js project breaks module resolution because Next.js is not a Node.js ESM loader.
Step by step#
- Open your terminal and run
nvm install 20.15.0 && nvm use 20.15.0. - Run
npm install typescript@5.4.5 @types/node@latest @supabase/supabase-js@latest. - Open
tsconfig.jsonand set"module": "esnext"and"moduleResolution": "bundler"(the Next.js defaults). - Add
"esModuleInterop": trueand"skipLibCheck": trueif missing. - Update
package.jsonto set"engines": { "node": ">=20.0.0" }. - Run
npm run buildto verify.
Verify the fix#
Run:
# Check versions
node -v && npm -v && npx tsc --version
# Expected output:
v20.15.0
9.8.1
Version 5.4.5Then:
# Install missing dev dependencies
npm install --save-dev ts-jest@29.1.1 @types/jest@29.5.13
# Run type check
npx tsc --noEmitYou should see:
Found 0 errors.If you’re still seeing Cannot find module '@types/node', run:
npm install --save-dev @types/node@latestIf you see Property 'auth' does not exist, verify @supabase/supabase-js is up to date:
npm ls @supabase/supabase-js
npm install @supabase/supabase-js@latestIf you're still seeing the error, two common variants exist:
Variant A — npm ERR! peer optional dependency failed#
This happens when @next/eslint-plugin-next has a peer dependency range that does not yet cover the TypeScript version you installed.
Fix by running:
npm install --save-dev @next/eslint-plugin-next@latestnpm 9 will auto-resolve compatible versions — no manual downgrade needed.
Variant B — Jest fails with Cannot find module 'ts-jest'#
This occurs when ts-jest is before v29 and TypeScript is 5.4.5.
Fix by updating jest.config.js:
// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
}Then run:
npm install --save-dev ts-jest@29.1.1 @types/jest@29.5.13Why this happens (and how to avoid it next time)#
TypeScript 5.4+ tightened module resolution and stricter type inference. It erases all types at compile time — no runtime type checks are added. If you see type errors after upgrading TypeScript, the cause is always a compile-time definition mismatch, not a runtime enforcement change.
The underlying invariant is: TypeScript’s type system is only as safe as the type definitions it reads. Outdated @supabase/supabase-js or @types/node packages are the most common culprit after a TypeScript version bump.
To avoid this next time:
- Always declare
"engines": { "node": ">=20.0.0" }inpackage.json. - Use
npm ci(notnpm install) in CI pipelines to enforce exact versions. - Run
npm ls typescriptbefore deploying to catch version mismatches. - For Next.js projects, keep
"module": "esnext"and"moduleResolution": "bundler"intsconfig.json— these are thecreate-next-appdefaults and what Next.js’s bundler expects.
I cover this in detail in TypeScript Migration Guide 2024: Upgrade JavaScript Projects Safely, including how to migrate legacy CommonJS projects without breaking Jest or ESLint.
Related#
Related fixes & guides
- Fix useEffect Running Twice in React 18 — Strict Mode
- Next.js Hydration Mismatch Error: Production Fix Guide
- Next.js revalidatePath Not Working: Production Fix Guide for App Router
- Next.js Server Actions with Supabase: Complete Guide
- Next.js Server Actions vs API Routes in Production: Decision Guide
- Production RAG with Supabase pgvector and Next.js
- How to Access Route Parameter Inside getServerSideProps
- Next.js 15 Minimum Node.js Version 18.18.0
- Supabase Auth Error Codes Explained: Fixes + TypeScript Cheat Sheet (2026)
- Fix ChunkLoadError: Loading Chunk Failed in Next.js