AniUI Academy

The Native TypeScript Compiler

TypeScript 7 ships a compiler rewritten in Go — tsc, tsserver and the language service running native. The type system itself is unchanged; the win is speed.

10 min read

The tsc you've been running through this entire track is a JavaScript program running on Node — a compiler for TypeScript, written in TypeScript, bundled and executed by the V8 engine inside your node process. That's the only tsc there has been, since TypeScript's earliest days. TypeScript 7 is where that changes: the compiler, the language server (tsserver), and the language service that your editor talks to have all been rewritten in Go and ship as a native binary.

The important thing to get right up front: this is a tooling rewrite, not a type-system rewrite. The code you write, the errors you get, the inference the compiler performs — all of that is the same. The compiler that reads your code just happens to be about ten times faster now.

What stayed the same

Everything in this track so far — basic types, narrowing, generics, utility types, mapped types, template literal types, strict flags, satisfies, declaration files — is exactly the same under the native compiler as under the JS-based one. A program that type-checked under TypeScript 6 type-checks the same way under TypeScript 7.

That matters enough to be worth stating explicitly, because "rewrite" is a word that normally implies "and you'll have to learn new things." In this case: the rewrite was specifically scoped to keep the type system identical. The point was to make the existing TypeScript fast, not to make a new TypeScript.

The surface area that genuinely changed is small enough to list in one place:

  • A handful of compiler-internal APIs used by tooling authors (not by application code).
  • A couple of inference edge cases where the old compiler's behaviour was known to be inconsistent and the native compiler's is the one the spec actually describes.
  • The exact shape of some diagnostic messages, because the implementer took the opportunity to clean up how errors are phrased.

None of that is work for an app developer to care about. If any of it breaks a project, the fix is the same scale as a TypeScript point release — tighten a corner case, re-run.

What actually got faster, and why

The headline target — repeatedly quoted by the team through the native compiler's long preview — is roughly 10x. On a large monorepo where a cold tsc --noEmit used to take two minutes, it's measurable in seconds. For smaller projects the ratio holds but the absolute wall clock was already short, so you feel it more in CI fan-out and editor responsiveness than in a single invocation.

The responsiveness part is the one most worth paying attention to. tsserver — the long-running language-service process that your editor queries for hover info, autocomplete, "find references," and the red squiggles — is subject to the same rewrite, which means hover response, diagnostics on save, and "go to definition" on a cold file all feel noticeably faster. In a large project that's the difference between an editor that keeps up with you and one you learn to work around.

The reason these wins exist, as opposed to being a single clever optimisation, is structural:

  • Parallelism. A Go program can use real OS threads to type-check multiple files in parallel. A Node-hosted JS program effectively cannot, except by spawning worker processes with their own startup cost.
  • Memory layout. The internal data structures the compiler uses — symbol tables, type caches, the shape of an AST node — can be laid out more tightly in native code than they can as JS objects, which pays off at the scale of a million allocations per compile.
  • No JIT warmup. A short-lived tsc --noEmit on a CI machine used to spend measurable time warming up the V8 JIT before hitting steady state. Native code skips that step entirely, which is disproportionately useful for the "run on every commit" use case.

None of these are tricks. They're consequences of moving off a Node host, which is why the speed-up wasn't realistically extractable from the old implementation.

What your project actually has to do to adopt it

For most projects: upgrade the typescript package, re-run your build. The compiler reads the same tsconfig.json and emits the same diagnostics. The editor picks up the new tsserver automatically through its existing TypeScript integration (VS Code, JetBrains IDEs, and the common Neovim LSP setups all hand the version-resolution job to the project's installed typescript).

Two things are worth checking the first time:

// tsconfig.json — unchanged in shape; still the same options
{
  "compilerOptions": {
    "strict": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "target": "es2022"
  }
}
  • Any custom tooling that depended on the TypeScript compiler's internal JS APIs (ts-morph, transformers, custom ts-loader plugins) needs to be on a version that's been updated for TS 7. The public, documented APIs are stable; the internals, deliberately, are not.
  • CI caches keyed on the TypeScript version will be invalidated on first upgrade. Expect one slow CI run, then a much faster steady state.

The point of calling out these small checks is to be honest about where the migration is not zero work. Everywhere else, the right expectation is: same TypeScript, your npm run tsc finishes in a tenth of the time.

How this changes the shape of a workflow

Speed changes behaviour. Three concrete ways a 10x compiler lands in how a team works:

  • Pre-commit type-checking becomes realistic. Running tsc --noEmit as part of a Husky-style pre-commit hook on a large codebase used to be unacceptable — too slow, too interruptive. At the new speed, it's often fine.
  • CI gets cheaper and more iterable. A type-check step that was minutes long on every PR becomes seconds. Smaller matrices, more frequent runs, less justification for "we only type-check on main."
  • Editor-driven refactors feel different. A "rename symbol" across thousands of files, a "find all references" through the whole project, a "check this against the current tsconfig" — operations that used to take enough time to break your train of thought now finish inside one.

None of that is required. You can adopt the native compiler, change nothing about your workflow, and still get the wall-clock win. The workflow changes are what teams tend to opt into once the cost structure of type-checking actually changes.

What to remember

  • TypeScript 7 ships a native compiler: tsc, tsserver, and the language service are rewritten in Go and run as a native binary. The type system is unchanged.
  • The target is roughly a 10x speed-up on typical real-world projects; the biggest user-visible wins are in editor responsiveness and in large-project CI.
  • The gains are structural — real OS parallelism, tighter memory layout, skipping JIT warmup — not a single optimisation; the old Node-hosted compiler could not realistically have reached the same number.
  • Upgrading is mostly a package bump. Watch for custom tooling that depends on internal compiler APIs and for the one-time CI cache invalidation.
  • Workflow changes (pre-commit type-check, smaller CI matrices, faster editor refactors) are opt-in consequences of the new cost structure, not mandatory migration steps.

Check yourself

4 questions · pass 3/4 to unlock Upgrading to TypeScript 6 and 7

up to 50
  1. 1.What was rewritten in the move to TypeScript's native compiler?

  2. 2.Roughly what order of magnitude of speedup does the native compiler target compared with the previous JS-based tsc?

  3. 3.Which of these is the *honest* reason a native binary is faster than the JS-based compiler, more than any single micro-optimization?

  4. 4.Your project is still pinned to TypeScript 6 while a library you depend on only publishes types tested on TypeScript 7. What is the realistic expectation?

4 left to answer

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.