TypeScript 6.0 Beta: Preparing for the Go Rewrite
TypeScript 6.0 beta dropped on February 11th, and honestly? The release notes read less like a feature announcement and more like a farewell letter. This release wraps up the JavaScript-based TypeScript compiler for good. The next major version — TypeScript 7.0 — ships the native Go compiler Anders Hejlsberg first announced almost exactly a year ago, on February 28, 2025.
The team chose 6.0 as the version to rip out everything that won’t survive the transition. They’re not being gentle about it.
Why Go, Quick Recap #
If you missed the original announcement (or blocked it out), here’s the short version. The TypeScript compiler — written in TypeScript, running on Node.js — has hit performance ceilings that no optimization tricks can fix. Large codebases take minutes to type-check. IDE responsiveness tanks as projects grow. Memory consumption? Scales terribly.
The native Go port promises 10x build speed improvements and substantially lower memory usage. The team previewed it mid-2025 and the benchmarks were convincing. Not “a little faster.” Fundamentally, architecturally faster — the kind of performance gap that changes how you interact with the language day-to-day.
TypeScript 6.0 exists to get the ecosystem ready for that jump, even if it means breaking things now.
The New Defaults #
Several compiler defaults changed, and this where most projects feel the impact first.
strict: true is now the default. You used to opt in; now you opt out. If your project wasn’t already running strict mode (and look, in 2026, it really should be), expect a wall of type errors on your next upgrade. Strict mode has existed since TypeScript 2.3 — making it the default isn’t a new capability, it’s an editorial statement about how TypeScript ought to be used.
module: esnext is the default. CommonJS no longer gets assumed. If you’re still emitting require() calls, set module: commonjs explicitly. The ecosystem has been drifting toward ESM for years; this just makes it official.
target: es2025 is the default. No more downleveling modern syntax by default. Need older runtimes? Set the target yourself. The assumption: your runtime supports current JavaScript.
Put together, these defaults tell you exactly who TypeScript 6.0 targets — modern codebases, current runtimes, strict type checking. If that already describes your project, the upgrade should go smoothly. If it doesn’t, well, the upgrade becomes a forcing function. Which I suspect is the point.
What Got Removed #
This section causes the most pain for legacy codebases. I’ll keep it blunt.
--outFile is gone. The option that concatenated all output into a single file — a relic from before bundlers existed. The Go compiler won’t support it. If you’re still using --outFile, get a bundler. Vite, webpack, esbuild, Rollup; pick one, any one.
Module formats amd, umd, and systemjs are removed. These haven’t been relevant for most projects in years. But if you maintain a library that ships UMD builds through TypeScript’s compiler (rather than a separate bundler), you need to restructure now. Bundle externally.
--moduleResolution classic is removed. The legacy resolution algorithm predating Node’s module resolution. If this existed in your tsconfig, it was almost certainly there by accident or inertia. You won’t miss it.
esModuleInterop: false no longer works. The option controlling how TypeScript handled default imports from CommonJS modules — always on now. If your code uses import * as React from 'react' instead of import React from 'react', TypeScript won’t complain, but the interop behavior is locked either way.
What Got Deprecated #
Deprecations are warnings, not removals. But they signal what TypeScript 7.0 will drop, so pay attention.
target: es5 is deprecated. If you’re still targeting ES5 (and I have to ask: why?), start planning your migration. The Go compiler almost certainly won’t support it.
--baseUrl is deprecated. Use paths with explicit mappings instead. The baseUrl behavior created ambiguity and caused subtle resolution bugs that were genuinely maddening to debug.
--moduleResolution node is deprecated in favor of node16 or nodenext. The original node resolution didn’t handle ESM/CJS interop correctly; it was a source of confusion for years.
--downlevelIteration is deprecated. With the default target at es2025, downleveling iterators becomes unnecessary for most use cases.
The Bridge Flag: --stableTypeOrdering
#
Here’s the feature most directly tied to the Go transition, and the one I find most interesting from an engineering perspective.
TypeScript’s current compiler sometimes produces non-deterministic ordering of union members and object properties in its output. The JavaScript implementation relies on hash maps whose iteration order isn’t guaranteed across runs; two builds of the same code might produce slightly different .d.ts files. In practice, most people never notice. In theory, it’s been a source of flaky snapshot tests and confusing diffs for ages.
The Go compiler uses different data structures with different ordering guarantees. --stableTypeOrdering forces the current JS compiler to match Go’s output — consistent, deterministic ordering.
The catch: up to 25% performance hit. Stable ordering requires additional sorting passes. For a single build that’s annoying but manageable. For watch mode in a large codebase, you’ll feel it.
My recommendation: enable it in CI, skip it for local dev. Run your full test suite with --stableTypeOrdering to catch any code that accidentally depends on current ordering behavior. When TypeScript 7.0 ships, stable ordering becomes the only ordering — better to discover breakages now than when the compiler forces the issue.
New Features (Yes, There Are Some) #
Not everything here involves removals and deprecations. TypeScript 6.0 does add ES2025 support, including some stuff I’ve been waiting for.
Temporal API types. The Temporal namespace now lives in TypeScript’s standard library types. If you’ve been wanting to use Temporal.PlainDate, Temporal.ZonedDateTime, and the rest with proper type support — it’s here. The API itself remains a Stage 3 proposal, but TypeScript ships the types in anticipation of finalization. (Personally, I can’t wait to stop reaching for date-fns every time I need timezone-aware dates.)
Map and WeakMap upsert. The .emplace() method (insert if absent, update if present) now has types. Small addition, but it eliminates that annoying .has() then .set() pattern I’ve written hundreds of times.
RegExp.escape. Typed support for escaping special regex characters. Minor, welcome.
Subpath imports with #/. Node’s subpath imports (#utils/logger, #config/database) now get full TypeScript resolution support. This is a cleaner alternative to path aliases for monorepos and large projects — and honestly, I think path aliases were always kind of a hack anyway.
Smarter this inference. The type checker got better at inferring this in functions that don’t use it, reducing false positives in strict mode. One of those quality-of-life improvements that eliminates a category of annoying type errors you’ve probably just been suppressing.
What I’d Do Right Now #
If you maintain a TypeScript project, here’s my approach.
Upgrade to the 6.0 beta in a branch. Turn on --stableTypeOrdering. Fix whatever breaks. Most breakages come from the new defaults (strict mode, ESM, es2025 target), not from the removals — unless you rely on --outFile or AMD modules, in which case you have bigger decisions ahead.
Run your full test suite. If you publish a library, pay close attention to .d.ts output. Stable ordering may change your public type signatures in ways that aren’t technically breaking but could surprise consumers who depend on specific import patterns.
Check your build pipeline for tools that call TypeScript’s compiler directly rather than going through a bundler. ts-node, tsx, esbuild, swc — they all need updates for 6.0 compatibility. Most have beta support already, but verify; don’t assume.
And start thinking about TypeScript 7.0. The Go rewrite isn’t a point release. It’s a new compiler. The 6.0 bridge gives you a window to surface compatibility problems before the old compiler disappears entirely.
That window won’t stay open forever.