TypeScript 7.0 Beta Is Out — The Compiler Is Now Written in Go and It's 10x Faster

TypeScript 7.0 Beta dropped yesterday. The entire compiler has been ported from TypeScript/JavaScript to Go, and the numbers are real. The Sentry codebase drops from 133 seconds to 16. Editor startup drops from 9.6 seconds to 1.2. Memory usage is roughly halved.

Yesterday, April 21, 2026, Daniel Rosenwasser posted on the TypeScript blog with the energy of someone who has been sitting on a secret for a year: TypeScript 7.0 Beta is available, and the entire compiler is now written in Go.

Not incrementally optimized. Not rewritten in Rust like everyone expected. Ported to Go — methodically, structurally, file by file — by a team that decided pragmatism was worth more than the idealistic choice. And the numbers are not hype. The VS Code codebase, 1.5 million lines of TypeScript, compiles in 78 seconds today with tsc. With tsgo, it takes 7.5 seconds. The Sentry codebase drops from 133 seconds to 16. Editor startup for VS Code's project drops from 9.6 seconds to 1.2. Memory usage is roughly halved.

This is the biggest architectural change in TypeScript's 12-year history. Here's everything you need to know.

Why the JavaScript Compiler Had to Die

TypeScript launched in 2012 self-hosted — the compiler was written in TypeScript itself, compiling to JavaScript, running on Node.js. This was elegant and philosophically satisfying. It was also a bet that eventually stopped paying out.

JavaScript is optimized for UI and browser work. It's JIT-compiled, meaning there's startup cost every time you run it. The TypeScript compiler built up over a decade into something processing enormous ASTs, running complex type inference across hundreds of thousands of files, and doing it all in a single-threaded JavaScript runtime that was never designed for this workload.

As TypeScript's adoption exploded — it overtook JavaScript as the most popular language on GitHub in August 2025 — the gap between what developers expected from their tooling and what a JavaScript-based compiler could deliver kept widening. Enterprise codebases with millions of lines of TypeScript were sitting through multi-minute builds. The language service in VS Code struggled to give instant feedback on large projects. Teams were watching 2-minute type-check runs in CI and quietly training themselves to ignore errors rather than fix them. The team was bumping against the ceiling of what they could squeeze out of the JS runtime.

So they started Project Corsa. The codename is Italian for "race." The original JavaScript implementation got a codename too: Strada, Italian for "road." They were replacing the road with the race car.

Why Go, Not Rust

Every developer who saw the announcement immediately asked the same question. Rust would be the obvious choice. It's a systems language, it's fast, it doesn't have GC pauses, it's memory safe, it's what half of the tooling ecosystem has been migrating toward. Why Go?

Ryan Cavanaugh, TypeScript's dev lead, answered this directly in the GitHub FAQ at github.com/microsoft/typescript-go:

The team had two real options: do a from-scratch rewrite in Rust, which would take years and produce a compiler with different semantics that no one could actually trust, or port to Go in roughly a year and end up with something near-identical in behavior to what developers already rely on.

This was not an accident of preference. Go's idiomatic style matched the existing TypeScript codebase closely enough that the port was a structural translation, not a redesign. The Go code looks familiar to anyone who has read the TypeScript compiler source. The type-checking logic, the algorithms, the data structures — all ported, not reinvented. The result is a compiler Rosenwasser describes as "structurally identical to TypeScript 6.0" in its type-checking behavior.

There are also practical reasons Go beats Rust for this specific problem. A compiler manipulates complex interconnected data structures — abstract syntax trees, type graphs, symbol tables — that all reference each other. Rust's ownership model makes shared mutable state genuinely painful to work with. Go's garbage collector handles that complexity without forcing constant ownership annotations throughout a 100,000-line codebase. For the TypeScript compiler's workload, GC pauses are not a meaningful concern — you're not building a game engine or a real-time trading system.

The concurrency story matters too. Go's goroutines and shared memory model let the compiler parallelize work in ways that JavaScript's worker threads cannot easily achieve. Workers in Node.js communicate via message passing. The TypeScript compiler's data structures don't divide cleanly into isolated chunks — the type checker needs shared access to the same program representation. Go handles this naturally.

About half the performance gain comes from native code execution. The other half comes from parallelism that the JavaScript runtime structurally cannot provide.

The Performance Numbers

From Microsoft's benchmarks confirmed by the beta release, across real-world codebases:

Command-line compilation:

Codebase TypeScript 6.0 TypeScript 7.0 (Go) Speedup
VS Code (~1.5M LOC) ~78s ~7.5s ~10x
Sentry ~133s ~16s ~10.2x
Playwright ~11s ~1.1s ~10x
TypeORM ~4s ~0.3s ~13x
TypeScript itself ~5s ~0.5s ~10x

The speedup correlates with project size. Small single-file projects see less dramatic improvement. Large monorepos with thousands of files see the full compounding effect of parallelism on top of native execution. The Sentry and VS Code numbers are the ones that matter for teams running enterprise codebases — 133 seconds down to 16 is not a productivity upgrade. It's a different category of tool.

Editor experience:

  • VS Code project load time: 9.6 seconds → 1.2 seconds (8x faster)
  • Memory usage: roughly halved
  • Language service project load in tsserver: was ~9.6s, new native service: ~1.2s
    Teams at Bloomberg, Canva, Figma, Google, Lattice, Linear, Miro, Notion, Slack, Vanta, Vercel, and VoidZero have all been running pre-release builds. Rosenwasser's announcement says the feedback has been "overwhelmingly positive" with teams reporting similar speedups. That's a meaningful validation set — none of those are small codebases.

The Go compiler passes 19,926 out of 20,000 compiler test cases. 99.6% compatibility. The remaining 74 edge cases are documented in GitHub issue #61754. If your codebase is in the lucky 99.6%, you can drop tsgo --noEmit into CI today and see the numbers. If you're in the 0.4%, you'll find out immediately.

How to Install and Use It Right Now

The beta is installable today. The package name is temporary — it'll ship under the standard typescript package name when stable:

npm install -D @typescript/native-preview@beta

Then run tsgo in place of tsc:

npx tsgo --version
# Version 7.0.0-beta
 
# Zero-risk first test: type-check without emitting
npx tsgo --noEmit
 
# With project references (monorepos)
npx tsgo -b tsconfig.base.json
 
# Extended diagnostics to see what the speedup looks like
npx tsgo --noEmit --extendedDiagnostics

The tsgo executable accepts the same flags as tsc. Your existing tsconfig.json works. --noEmit is the zero-risk first move — it tells you immediately whether tsgo finds any new errors and how fast it runs on your codebase.

For package.json scripts on a monorepo, a typical migration looks like:

{
  "scripts": {
    "typecheck": "tsgo -b tsconfig.base.json",
    "typecheck:watch": "tsgo -b tsconfig.base.json --watch",
    "test": "tsgo -p . --noEmit && vitest"
  }
}

For the editor experience, install the TypeScript Native Preview extension for VS Code. It's built on LSP — Language Server Protocol — which means it works in other editors too. The move to LSP is significant: the old tsserver architecture predated the LSP standard and never properly conformed to it, which is why TypeScript integration in non-VS Code editors has always been rougher than it should be. The Go language service is LSP-native from the start. Neovim, Helix, Zed, and every other editor with LSP support gets first-class TypeScript 7.0 tooling without the workarounds that characterize TypeScript integration today.

Running Side-by-Side with TypeScript 6.0

The TypeScript team was careful about the transition path. Some tools — typescript-eslint being the main example — import from the typescript package directly as a peer dependency. You can't just swap the package name without breaking them.

Their solution: a compatibility package, @typescript/typescript6, which exposes a tsc6 entry point. Once TypeScript 7.0 ships stable as the typescript package with a tsc binary, you can run both without naming conflicts.

The recommended approach for projects using tools with typescript peer dependencies:

npm install -D typescript@npm:@typescript/typescript6

Or in package.json:

{
  "devDependencies": {
    "typescript": "npm:@typescript/typescript6@^6.0.0"
  }
}

This aliases typescript to the 6.x package, so typescript-eslint and similar tools keep working while you run tsgo from the 7.0 beta for your actual type-checking. You get the speed now; the tooling catches up later.

The Parallelization Architecture

TypeScript 7.0's performance doesn't come from native code alone. The compiler is redesigned to parallelize multiple stages of the build pipeline simultaneously.

Parsing and emit are embarrassingly parallel — each file can be processed independently. The Go compiler spins up goroutines for these stages and processes files concurrently. On a machine with multiple cores, this alone delivers 2-3x speedup over the sequential JavaScript pipeline.

Type checking is harder to parallelize. The type checker needs a consistent view of the entire program — types reach across files, and the order files are checked can affect results. TypeScript 7.0 solves this by creating a fixed pool of type-checker workers, each with its own view of the program. Each worker processes a deterministic subset of files. Given the same input, the division is always identical, so results are reproducible regardless of how many workers are running.

The --checkers flag controls this pool size, defaulting to 4:

# More workers for large codebases with many CPU cores
npx tsgo --checkers 8
 
# Fewer for CI runners with limited resources
npx tsgo --checkers 2
 
# Debug mode — single-threaded, deterministic, comparable to tsc behavior
npx tsgo --singleThreaded

For monorepos with project references, --builders runs multiple projects in parallel:

# Build 4 projects at once, each with 4 type-checker workers
npx tsgo --builders 4 --checkers 4
# Up to 16 type-checkers running simultaneously

Rosenwasser warns these multiply — --builders 4 --checkers 4 means potentially 16 simultaneous type-checkers, which can spike memory on constrained machines. For a 10-package monorepo, even --builders 2 --checkers 4 will dramatically change build times.

The --singleThreaded flag is specifically for comparing behavior between TypeScript 6 and 7, debugging type errors that might appear order-dependent, and CI environments where you want deterministic output.

The Breaking Changes That Will Actually Bite You

TypeScript 6.0 was explicitly designed as a bridge release — it deprecated legacy options and behaviors to prepare for 7.0. TypeScript 7.0 turns those deprecations into hard errors with no escape hatch.

New default values — changes that silently affect behavior:

  • strict is now true by default. If you were relying on lenient defaults, this will surface errors. All the flags strict enables — strictNullChecks, strictFunctionTypes, strictBindCallApply, noImplicitAny — are now on.
  • module defaults to esnext. Not commonjs. Not node16. ESNext.
  • noUncheckedSideEffectImports is true by default. Side-effect imports without corresponding type declarations will error.
  • types now defaults to []. The old behavior that automatically included all @types/* packages is gone.
  • rootDir defaults to ./. Projects with tsconfig.json outside of src need to explicitly set rootDir to preserve directory structure.
  • stableTypeOrdering is now true and cannot be turned off.
    The types change is probably the most invisible footgun in practice. Any project relying on globally declared types from @types/node, @types/jest, @types/mocha, or similar packages that worked automatically will now fail silently or with confusing errors until you explicitly declare them:
{
  "compilerOptions": {
    "types": ["node", "jest"]
  }
}

Options that are now hard errors (no longer accepted at all):

  • target: "es5" — ES5 output is gone. Use Babel, SWC, or esbuild for downleveling if you still need it.
  • downlevelIteration — gone with ES5 support.
  • --outFile — removed entirely. Concatenation-based bundling is dead; use webpack, Rollup, esbuild, or Vite.
  • moduleResolution: "node" / "node10" — use "nodenext" or "bundler".
  • module: "amd", "umd", "systemjs", "none" — all gone. Use "esnext" or "preserve" with a bundler.
  • baseUrl — removed. Use paths relative to the project root instead.
  • moduleResolution: "classic" — gone. "bundler" or "nodenext".
  • esModuleInterop: false — can no longer be disabled.
  • allowSyntheticDefaultImports: false — can no longer be disabled.
  • alwaysStrict: false — strict mode is always on.
    The esModuleInterop: false removal matters for specific legacy patterns. If you've been running with esModuleInterop: false because you had import * as React from 'react' patterns everywhere and didn't want to deal with the default import change, TypeScript 7.0 forces that migration.

The --outFile removal is the right call made eight years too late. No modern bundler should be using TypeScript's concatenation output. But if you're in a legacy codebase that still relies on it, this is a migration project, not a flag change.

The Tooling Ecosystem

This is the section the beta announcement buries. Not all TypeScript tooling transitions cleanly to 7.0.

Bundlers (Vite, webpack, esbuild, Rollup): Mostly fine. These tools strip TypeScript types at build time using their own transpilation rather than calling the TypeScript compiler API for every file. Vite users may find fewer edge cases after upgrading because the new default moduleResolution: bundler is what Vite has always used anyway. webpack's ts-loader and babel-loader work with the language rules but don't depend on the Compiler API for type-checking, so they're largely unaffected.

typescript-eslint: Requires specific handling for 7.0. The tool imports from typescript directly as a peer dependency. This is why the typescript@npm:@typescript/typescript6 aliasing strategy exists — it keeps typescript-eslint pointed at the 6.x API while your actual type-checking uses tsgo. The typescript-eslint team is working on 7.0 API support, but the timing of a new Compiler API (not until TypeScript 7.1 at the earliest) means the current library won't be able to fully migrate until that lands. For teams looking ahead, the OXC-based tsgolint uses the typescript-go codebase directly and is already adapting to the new architecture.

Biome v2: Worth calling out specifically. Biome launched its second major version as the first JavaScript/TypeScript linter with type-aware rules that doesn't require the TypeScript compiler at all. If your primary remaining reason to keep TypeScript 6.x around is typescript-eslint, Biome v2 offers an alternative path. The rules aren't identical but the coverage is substantial.

Custom transformers and compiler plugins: This is where the real pain lives. TypeScript 7.0 will not support the existing Strada Compiler API. A new Go-based Compiler API is being built, but it won't be stable until TypeScript 7.1. Any project using ts-patch, custom transformers, or tools that import from typescript and call the compiler API programmatically has migration work ahead. The timeline on 7.1 is "at least several months from now" per the beta announcement.

Next.js, Angular, React: Standard upgrade process. These use TypeScript via bundlers for transpilation and call into the type-checker through standard configuration paths. Next.js has historically moved quickly on TypeScript support. Angular has its own compatibility matrix worth checking before upgrading. React applications built with Vite should be among the smoother upgrades.

The practical recommendation from the community is to run two parallel paths during the transition: tsgo for fast type-checking and tsc6 (from @typescript/typescript6) for anything that needs the old API. Once 7.1 ships with a stable API, the tooling ecosystem will converge.

JavaScript Support Changes

TypeScript's JS support has always been a compromise — it tried to understand patterns from Closure, JSDoc, and whatever people happened to write. TypeScript 7.0 cleans this up. JS support now behaves more consistently with how .ts files are analyzed.

The changes affect JSDoc patterns specifically. These matter for codebases still using JavaScript with JSDoc type annotations (which is a meaningful number of projects, particularly older Node.js applications and libraries):

  • @enum is no longer specially recognized. Use @typedef on (typeof YourEnumDeclaration)[keyof typeof YourEnumDeclaration].
  • Values cannot be used where types are expected in JSDoc — write typeof someValue instead.
  • @class doesn't make a function a constructor anymore. Use an actual class declaration.
  • Postfix ! in JSDoc types is not supported — use T.
  • Closure-style function syntax in JSDoc (e.g., function(string): void) is gone — use TypeScript shorthand ((s: string) => void).
  • @typedef type names must be declared within the tag, not adjacent to an identifier.
  • Aliasing this and reassigning prototype wholesale are no longer specially handled.
    If you maintain a large JavaScript codebase with JSDoc type annotations, audit the TypeScript team's CHANGES.md in the typescript-go repo before anything else. Run npx tsgo --noEmit against your JS files specifically and expect more noise than you'd see on a TypeScript codebase.

The Migration Path

The recommended migration sequence is not "upgrade everything at once." It's:

Step 1: Get to TypeScript 6.0 first if you haven't already. TypeScript 6.0 is the bridge release specifically designed to surface everything that will break in 7.0. The deprecation warnings in 6.0 are your roadmap. The migration tool @andrewbranch/ts5to6 automates most of the mechanical tsconfig changes:

npx @andrewbranch/ts5to6

Run it. Then fix the errors it can't fix automatically.

Step 2: On your existing TypeScript 6.0 codebase, add tsgo --noEmit as a non-blocking CI job:

# GitHub Actions example
- name: TypeScript 7.0 beta check
  run: npx tsgo --noEmit
  continue-on-error: true  # non-blocking while you evaluate

This tells you immediately whether you're in the 99.6% that compiles clean with 7.0 semantics, and it tells you the exact performance difference on your actual codebase in CI — not on someone else's benchmark.

Step 3: If the non-blocking job is clean for a week, make it blocking. You now have a 10x faster type-check as your primary type-check gate.

Step 4: Audit the tooling. Anything that imports from typescript and calls the Compiler API needs a plan. Either alias it to @typescript/typescript6 for the short term, or evaluate whether Biome v2 covers your linting requirements without the TypeScript dependency.

Step 5: Wait for TypeScript 7.1 for the stable programmatic API before migrating any custom transformers or compiler plugins.

What's Still Coming Before Stable

The beta label is explicitly downplayed — Rosenwasser says you can probably use it in day-to-day work immediately. The type-checking logic is identical to 6.0, and the beta has been validated against a decade's worth of compiler tests and multiple million-line production codebases.

What's still coming:

  • A more efficient --watch implementation (current watch mode works, just not yet as fast as it will be)
  • Declaration file emit from JavaScript files (.js.d.ts)
  • Editor feature gaps: "find file references" from the file explorer, granular "sort imports" and "remove unused imports" commands
  • The stable programmatic API (TypeScript 7.1, not 7.0)
    The programmatic API gap is the most significant for the tooling ecosystem. It's why the side-by-side strategy exists. The CLI experience is ready for broad production use now. The API experience is coming in 7.1, at which point the tooling landscape will have time to migrate.

Timeline from the announcement: stable release within two months, release candidate a few weeks prior. Call it late June or early July 2026.

The Ecosystem Context

TypeScript 7.0's Go compiler isn't isolated. The frontend toolchain has been going polyglot for years — Rust-based tools like SWC, esbuild, Biome, Rolldown, and Oxc have been taking over the transpilation and bundling layers precisely because JavaScript runtimes are wrong for CPU-intensive tooling. TypeScript 7.0 is the final major piece of the developer toolchain completing that transition.

The important distinction: SWC and esbuild strip TypeScript types without type-checking. They're fast because they don't do the hard part. TypeScript 7.0's tsgo does the full type-checking work — the semantics are identical to 6.0 — and is still 10x faster. These are not competing tools. SWC/esbuild are your build transpilers; tsgo is your type-checker. Running both is already the standard pattern in modern setups, and TypeScript 7.0 makes the type-checking half of that pair as fast as the transpilation half.

For AI coding tools, the speed matters differently. Copilot, Claude, and similar AI assistants that work within your editor need low-latency access to semantic type information to provide meaningful suggestions. A language service that loads in 1.2 seconds rather than 9.6 means the AI assistant has a complete understanding of your codebase available from the moment you open it, rather than operating on partial information while the language service warms up. Rosenwasser specifically mentioned this in the original Project Corsa announcement: the new foundation enables AI tools to "learn, adapt, and improve the coding experience" in ways the JavaScript language service couldn't support.

Install it. Run npx tsgo --noEmit on your codebase today. If it reports no new errors — and for most codebases with TypeScript 6.0 compatibility, it won't — you're already looking at your future build pipeline.

# The zero-risk test for any TypeScript codebase
npm install -D @typescript/native-preview@beta
npx tsgo --noEmit

The JavaScript fundamentals series covers how the JavaScript runtime that TypeScript 6.0 and earlier compiled to actually works — the V8 engine, the JIT compiler, and the memory model that made the Go port necessary. The TypeScript overview covers the language itself for anyone new to the ecosystem. The Node.js explainer covers the runtime environment where most TypeScript server-side code executes.