writing/tutorial/2026/06
TutorialJun 3, 2026·30 min read

TypeScript 6.0 Complete Guide: New Features, Breaking Changes & Migration

Master TypeScript 6.0 — the last JavaScript-based release. Learn all new features, breaking changes, configuration defaults, Temporal API support, and how to migrate your project from TypeScript 5.x.

TypeScript 6.0 landed on March 20, 2026, and it is the most consequential TypeScript release in years. Not because of a flashy new type operator — but because it is the last version of the TypeScript compiler written in JavaScript. TypeScript 7 will ship a Go-based compiler that promises 10x faster builds. TypeScript 6.0 exists to bridge that gap: it hardens defaults, removes legacy baggage, and introduces real new features like built-in Temporal API types.

If you upgrade without reading the release notes, your CI will break. This guide walks you through everything that changed, with code examples and a step-by-step migration checklist.

Prerequisites

Before starting, ensure you have:

  • Node.js 18 or higher installed
  • A TypeScript project currently on TypeScript 5.x
  • Basic familiarity with tsconfig.json
  • A code editor (VS Code is recommended)

What You Will Build

By the end of this guide you will have:

  1. A fully migrated tsconfig.json compatible with TypeScript 6.0
  2. Hands-on examples of every significant new language feature
  3. A working understanding of the Temporal API types
  4. A clear picture of what TypeScript 7 (Go compiler) means for your workflow

Step 1: Install TypeScript 6.0

Start by upgrading your project:

npm install typescript@6 --save-dev
# or
pnpm add typescript@6 --save-dev

After installing, run the compiler immediately to see what breaks:

npx tsc --noEmit 2>&1 | head -50

You will likely see errors related to deprecated configuration options or strict mode violations. Do not panic — each error maps to a section of this guide.


Step 2: Understand the New Default Configuration

TypeScript 6.0 changed nine tsconfig.json defaults. If your config relies on implicit defaults, your build behavior will silently change. Here is a before/after comparison:

OptionTS 5.x DefaultTS 6.0 Default
strictfalsetrue
modulecommonjsesnext
targetes3es2025
moduleResolutionnodebundler
esModuleInteropfalsetrue
typesall visible[] (empty)
rootDirinferredtsconfig directory

Action: Make All Defaults Explicit

The safest migration approach is to pin every default explicitly in your tsconfig.json, so future TypeScript upgrades cannot silently shift behavior:

{
  "compilerOptions": {
    "target": "es2022",
    "module": "esnext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "types": [],
    "rootDir": "./src",
    "outDir": "./dist"
  }
}

If you need the old behavior while migrating incrementally, add:

{
  "compilerOptions": {
    "ignoreDeprecations": "6.0"
  }
}

This suppresses deprecation warnings temporarily. It will not work in TypeScript 7.0, so treat it as a time-limited crutch, not a permanent fix.


Step 3: Handle Breaking Changes

3.1 — Strict Mode Is Now On By Default

strict: true enables a bundle of strictness flags:

  • strictNullChecks
  • strictFunctionTypes
  • strictBindCallApply
  • strictPropertyInitialization
  • noImplicitAny
  • noImplicitThis
  • useUnknownInCatchVariables

If your project did not have strict: true before, you will now see errors like:

// Error TS 6.0: Object is possibly 'undefined'
function greet(name: string | undefined) {
  return "Hello " + name.toUpperCase(); // ❌
}
 
// Fix: add null check
function greet(name: string | undefined) {
  return "Hello " + (name ?? "stranger").toUpperCase(); // ✅
}

For large codebases, enable strict flags individually and fix them one at a time:

{
  "compilerOptions": {
    "strict": false,
    "strictNullChecks": true,
    "noImplicitAny": true
  }
}

3.2 — ES5 Target Is Removed

If you had "target": "es5" in your config, TypeScript 6.0 will error:

error TS5095: Option 'target=ES5' is deprecated and will stop functioning in TypeScript 7.0.

Modern browsers and Node.js all support ES2015 natively. Update your target:

{
  "compilerOptions": {
    "target": "es2022"
  }
}

If you truly need ES5 output for legacy browser support, use a build tool like Babel or SWC as a transpilation step after TypeScript type-checking.

3.3 — AMD and UMD Module Formats Are Deprecated

// ❌ Deprecated in TS 6.0
{
  "compilerOptions": {
    "module": "amd"
  }
}
 
// ✅ Use instead
{
  "compilerOptions": {
    "module": "esnext"
  }
}

3.4 — outFile Is Removed

The outFile option concatenated all output into a single file — a legacy pattern from pre-bundler era TypeScript. It is now removed entirely. Replace it with a proper bundler: Vite, Rollup, tsdown, or esbuild.

3.5 — baseUrl Standalone Is Deprecated

baseUrl without paths is deprecated. Use explicit path mappings:

// ❌ Deprecated
{
  "compilerOptions": {
    "baseUrl": "./src"
  }
}
 
// ✅ Use paths instead
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Step 4: Use the Automated Migration Tool

For the two most disruptive changes (baseUrl removal and rootDir inference), use the official ts5to6 migration tool:

npx ts5to6

This tool scans your tsconfig.json and automatically:

  • Converts standalone baseUrl to explicit paths
  • Adds explicit rootDir where it was previously inferred
  • Flags options that need manual review

Run it first, then address any remaining errors manually.


Step 5: Explore New Language Features

5.1 — Temporal API Built-In Types

The Temporal API — a modern replacement for Date — has reached Stage 4 and TypeScript 6.0 includes built-in type declarations for it. No polyfill or @types package needed.

Enable it in your config:

{
  "compilerOptions": {
    "target": "esnext",
    "lib": ["esnext", "esnext.temporal", "dom"]
  }
}

Then use it with full type safety:

// Get current date and time
const now = Temporal.Now.plainDateTimeISO();
console.log(now.toString()); // "2026-06-03T12:00:00"
 
// Add duration
const nextWeek = now.add({ days: 7 });
console.log(nextWeek.toString()); // "2026-06-10T12:00:00"
 
// Calculate difference between dates
const deadline = Temporal.PlainDateTime.from("2026-12-31T23:59:00");
const diff = now.until(deadline);
console.log(`${diff.days} days until year end`);
 
// Time zone aware
const meetingInParis = Temporal.ZonedDateTime.from({
  timeZone: "Europe/Paris",
  year: 2026,
  month: 6,
  day: 15,
  hour: 14,
  minute: 30,
});
console.log(meetingInParis.toString());

Key Temporal classes and their TypeScript types:

ClassDescriptionTypeScript type
Temporal.PlainDateCalendar date without timeTemporal.PlainDate
Temporal.PlainTimeTime without dateTemporal.PlainTime
Temporal.PlainDateTimeDate + time, no timezoneTemporal.PlainDateTime
Temporal.ZonedDateTimeDate + time + timezoneTemporal.ZonedDateTime
Temporal.InstantAbsolute UTC momentTemporal.Instant
Temporal.DurationLength of timeTemporal.Duration

Note: If your project uses temporal-polyfill or @js-temporal/polyfill, those package types are not interassignable with the new built-in types. Remove the polyfill once your runtime environment supports Temporal natively (Node.js 22+ includes it).

5.2 — Improved Method Type Inference

TypeScript 6.0 fixes a long-standing limitation where method signatures in generic types were not inferred as precisely as arrow functions. This affects especially fluent builder patterns:

class QueryBuilder<T> {
  filter(predicate: (item: T) => boolean): this {
    // implementation
    return this;
  }
 
  sort(comparator: (a: T, b: T) => number): this {
    // implementation
    return this;
  }
}
 
// TypeScript 6.0 now correctly infers the return type chain
const result = new QueryBuilder<User>()
  .filter(u => u.active)      // correctly typed as QueryBuilder<User>
  .sort((a, b) => a.age - b.age); // still QueryBuilder<User>

5.3 — Subpath Imports with #/ Prefix

TypeScript 6.0 adds first-class support for Node.js subpath imports using the #/ prefix. Define them in package.json:

{
  "imports": {
    "#/utils": "./src/utils/index.ts",
    "#/config": "./src/config.ts",
    "#/*": "./src/*.ts"
  }
}

Then use them in TypeScript with full type resolution:

import { formatDate } from "#/utils";
import { appConfig } from "#/config";

TypeScript 6.0 resolves these to the correct source files without additional configuration.

5.4 — ES2025 Target and Library

The new "target": "es2025" emits modern JavaScript features natively:

  • Promise.try()
  • Import attributes (import data with { type: "json" })
  • RegExp.escape()
  • Float16Array
// With target: "es2025", TypeScript won't down-level these
const result = await Promise.try(() => riskyOperation());
 
import data from "./data.json" with { type: "json" };
 
const escaped = RegExp.escape("hello.world"); // "hello\\.world"

Step 6: Performance Improvements in Practice

TypeScript 6.0 delivers measurable performance gains:

  • 40-60% faster incremental compilation — the compiler now caches type resolution results more aggressively
  • 25% reduced memory usage — peak memory consumption drops significantly for large codebases
  • 30% faster editor operations — inlay hints, hover types, and go-to-definition are noticeably snappier

You do not need to change any code to benefit from these improvements. They apply automatically after upgrading.

To benchmark your build times:

# Before upgrade
time npx tsc --noEmit
 
# After upgrade to 6.0
time npx tsc --noEmit

For monorepos or projects with more than 1,000 source files, the improvement is especially dramatic because TypeScript now shares type resolution caches across project references.


Step 7: Verify Your Migration

After applying all changes, run a full type-check to confirm everything is clean:

npx tsc --noEmit

For projects using Jest or Vitest with ts-jest or @vitest/coverage-v8, also verify tests still pass:

npm test

Check your build output to ensure modules are emitting in the expected format:

npm run build
ls -la dist/

A successful migration produces:

  • Zero TypeScript errors on tsc --noEmit
  • All tests passing
  • Build output in the correct module format

Step 8: Prepare for TypeScript 7

TypeScript 7.0 will ship the Go-based compiler (tsc-go). You will not need to change your TypeScript code — only how you invoke the compiler. The Go compiler offers:

  • 10x faster cold builds compared to TypeScript 6.0
  • Parallel file processing using Go goroutines
  • Drop-in replacement for the current tsc CLI

To prepare today:

  1. Remove all uses of ignoreDeprecations: "6.0" — they will error in TypeScript 7
  2. Ensure your tsconfig.json has no deprecated options
  3. Avoid tsc --build patterns that rely on outFile (already removed in 6.0)
  4. Test with the TypeScript 7 nightly if you want early feedback:
npm install typescript@next --save-dev

Troubleshooting

"strict is true but I want to migrate incrementally"

Enable individual strict flags instead of the umbrella strict: true:

{
  "compilerOptions": {
    "strict": false,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "strictFunctionTypes": true
  }
}

"Module not found after changing moduleResolution to bundler"

The bundler moduleResolution allows extensionless imports but requires your bundler (Vite, webpack, etc.) to also resolve extensions. If you are running tsc directly to emit, use "moduleResolution": "node16" instead.

"Temporal types conflict with polyfill"

Remove your polyfill package and its @types entry. With TypeScript 6.0, Temporal types are built-in:

npm uninstall temporal-polyfill @types/temporal-polyfill

"outFile was my bundling strategy"

Replace outFile with a proper bundler. For library publishing, tsdown is the current best option:

npm install tsdown --save-dev
npx tsdown --entry src/index.ts --format esm,cjs --dts

Next Steps

Conclusion

TypeScript 6.0 is a bridge release. It modernizes the language tooling by removing decade-old baggage, hardens defaults to match how developers actually configure projects today, and introduces the Temporal API as the first genuinely new JavaScript primitive TypeScript has typed in years. Migrating now takes a few hours but sets you up perfectly for the performance leap TypeScript 7 will deliver with its Go-based compiler.

The migration path is straightforward: run npx ts5to6, pin your config defaults explicitly, address strict mode violations incrementally, and you are done. Your codebase — and your future self waiting for 10x faster builds — will thank you.