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:
- A fully migrated
tsconfig.jsoncompatible with TypeScript 6.0 - Hands-on examples of every significant new language feature
- A working understanding of the Temporal API types
- 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-devAfter installing, run the compiler immediately to see what breaks:
npx tsc --noEmit 2>&1 | head -50You 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:
| Option | TS 5.x Default | TS 6.0 Default |
|---|---|---|
strict | false | true |
module | commonjs | esnext |
target | es3 | es2025 |
moduleResolution | node | bundler |
esModuleInterop | false | true |
types | all visible | [] (empty) |
rootDir | inferred | tsconfig 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:
strictNullChecksstrictFunctionTypesstrictBindCallApplystrictPropertyInitializationnoImplicitAnynoImplicitThisuseUnknownInCatchVariables
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 ts5to6This tool scans your tsconfig.json and automatically:
- Converts standalone
baseUrlto explicitpaths - Adds explicit
rootDirwhere 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:
| Class | Description | TypeScript type |
|---|---|---|
Temporal.PlainDate | Calendar date without time | Temporal.PlainDate |
Temporal.PlainTime | Time without date | Temporal.PlainTime |
Temporal.PlainDateTime | Date + time, no timezone | Temporal.PlainDateTime |
Temporal.ZonedDateTime | Date + time + timezone | Temporal.ZonedDateTime |
Temporal.Instant | Absolute UTC moment | Temporal.Instant |
Temporal.Duration | Length of time | Temporal.Duration |
Note: If your project uses
temporal-polyfillor@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 --noEmitFor 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 --noEmitFor projects using Jest or Vitest with ts-jest or @vitest/coverage-v8, also verify tests still pass:
npm testCheck 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
tscCLI
To prepare today:
- Remove all uses of
ignoreDeprecations: "6.0"— they will error in TypeScript 7 - Ensure your
tsconfig.jsonhas no deprecated options - Avoid
tsc --buildpatterns that rely onoutFile(already removed in 6.0) - Test with the TypeScript 7 nightly if you want early feedback:
npm install typescript@next --save-devTroubleshooting
"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 --dtsNext Steps
- Read the official TypeScript 6.0 release notes
- Explore the Temporal API documentation
- Follow the TypeScript 7 roadmap for Go compiler updates
- Check out our tutorial on Zod v4 schema validation for complementary runtime type safety
- Explore Effect-TS for advanced type-safe pipelines
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.