Home / Articles / TypeScript 7.0 Moves the Compiler to Go for Native Speed

This article is published in English.

TypeScript 7.0 Moves the Compiler to Go for Native Speed

TypeScript 7.0 ports tsc to Go with parallel checkers, new tsconfig defaults, Unicode template literals, stricter JS analysis, and a temporary programmatic API gap.

1086 words

For about fourteen years the TypeScript compiler could build itself. tsc was TypeScript that compiled to JavaScript and ran on Node. As repositories grew into millions of lines, that self-hosted design became a bottleneck.

TypeScript 7.0 changes the host language. The compiler and language service moved from TypeScript into Go. Microsoft describes the work as a port rather than a rewrite: type-checking structure matches 6.0, but execution is native code with shared-memory parallelism. Published comparisons often land near a 10× speedup versus TypeScript 6.0.

One frequently cited workload makes the shift concrete. Checking the VS Code tree — on the order of 1.5 million lines of TypeScript — fell from roughly 77.8 seconds to about 7.5 seconds.

If earlier coverage used the code name Project Corsa (with the legacy JavaScript tree nicknamed Strada), this release is that effort shipping.

Why Go, and why a port?

Public speculation often named Rust. Go was chosen because it lined up with the existing compiler’s shape: heavy graphs, garbage collection, and cyclic structures that are awkward to recreate from scratch. That alignment made a line-by-line port feasible.

The port framing matters more than the language brand. Keeping the architecture kept the rules. Projects that already type-check under 6.0 with stableTypeOrdering on and without ignoreDeprecations should see the same answers under 7.0 — a quicker engine, not a different type system.

Production soak testing came first. For over a year the port ran on huge trees at places such as Bloomberg, Figma, Google, Slack, Notion, and Vercel before this milestone.

Real parallelism

A single Node thread used to bound throughput. Native workers remove that cap. Version 7 spreads parse, check, and emit work and adds flags:

  • --checkers sets the count of parallel type-check workers
  • --builders parallelizes project-reference builds and stacks with --checkers in monorepos
  • --singleThreaded collapses everything onto one core for debug and baseline timings

Per-file parse/emit work scales with repository size and modularity; tiny one-file apps gain less.

Watch mode was rebuilt as well. Polling burned CPU on huge node_modules trees; bringing Parcel’s watcher into Go lowers that cost and reacts faster to edits.

Config changes that will trip teams

TypeScript 6.0 was the bridge: new defaults and deprecations appeared as warnings. 7.0 makes them hard errors. Teams that already passed through 6.0 have done most of the work. Jumping from 5.x straight to 7.0 needs tsconfig.json cleanup time.

Notable default flips:

  • strict turns on unless overridden
  • module lands on esnext, while target picks the latest stable ECMAScript edition short of esnext
  • noUncheckedSideEffectImports is on by default
  • libReplacement is off by default
  • stableTypeOrdering stays forced on
  • rootDir starts at ./
  • types starts as an empty list

Docs call out rootDir and types as the surprises teams hit first — and the ones with the simplest fixes.

If tsconfig.json sits above a src folder, set rootDir explicitly so emit layout stays familiar:

{
  "compilerOptions": {
    "rootDir": "./src"
  },
  "include": ["./src"]
}

Because types no longer auto-imports everything under node_modules/@types, list what you need:

{
  "compilerOptions": {
    "types": ["node", "jest"]
  }
}

Options that previously warned now fail hard (they stop doing anything useful):

  • Drop target: es5 and downlevelIteration
  • Replace legacy moduleResolution values (node, node10, classic) with nodenext or bundler
  • Retire module modes such as amd, umd, systemjs, and none in favor of esnext or preserve
  • Remove baseUrl and express paths relative to the project root
  • Keep esModuleInterop / allowSyntheticDefaultImports from being set to false
  • Treat alwaysStrict as permanently on

If moduleResolution is still set to the old node value after years without a review, that file is the migration checklist.

Unicode in template literal types

Template literal types now follow Unicode code points rather than UTF-16 code units:

type HeadTail<S> = S extends `${infer Head}${infer Tail}` ? [Head, Tail] : never;

type Result = HeadTail<"😀abc">;
// In 7.0:      ["😀", "abc"]
// Previously:  ["\ud83d", "\ude00abc"]

Older compilers could bisect an emoji’s surrogate pair. That mirrored JS indexing and rarely matched author intent. Iteration now follows code points the way for...of and [...str] do. Utilities that intentionally counted UTF-16 units will break; everyone else gets the behavior they expected.

Stricter JavaScript analysis

.js checking used to tolerate more JSDoc and Closure-era idioms. Release 7 tightens that path toward .ts rules:

  • Places that need types reject bare values — prefer typeof someValue
  • @enum / @class lose special handling; declare a real class or @typedef
  • A bare ? is not accepted as a type — prefer any
  • Trailing ! assertions are unsupported — write T explicitly
  • Old function(string): void forms give way to (s: string) => void

The programmatic API gap

A stable programmatic API is still missing in 7.0. Libraries that embed the compiler — ESLint’s TypeScript integration, ts-morph, hand-rolled transformers, plus editor helpers around Vue, Svelte, Astro, MDX, or Angular templates — therefore cannot switch completely yet. Microsoft treats the hole as temporary and points API completion at 7.1 and later releases.

Meanwhile, use 7.0 where language-server plugins are not required. Angular teams, for example, can run tsc from 7.0 for fast project-wide CLI checks while keeping 6.0 in the editor. A compatibility package, @typescript/typescript6, provides a tsc6 binary and re-exports the 6.0 API so both can coexist:

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

Should you upgrade?

On TypeScript 6.0 already, migration is small and payoff is large: adjust a few tsconfig knobs and gain faster CI plus snappier editor startup. Further back, the breakages are real, but nearly all were already signaled.

Install the release candidate today:

npm install -D typescript@rc

For editors, a VS Code add-on speaks LSP today, and native VS Code integration is expanding. Visual Studio detects 7.0 from the open workspace without a separate install step.

Maintainers say feature releases resume on the familiar multi-month rhythm, and 7.1 is expected to fill the embedding API hole.

Net result: familiar TypeScript rules, running as native code.