TypeScript 7.0 RC marks the most significant architectural shift in the compiler's history. The entire TypeScript compiler has been rewritten in Go, a project internally codenamed "Corsa," delivering up to roughly 9-10x faster build times across real-world codebases depending on project size (see benchmark table). This migration guide walks through the concrete steps needed to adopt the Go rewrite without breaking existing projects, covering installation, configuration changes, build pipeline updates, and the edge cases that trip teams up during the transition.
How to Migrate to TypeScript 7.0 RC (tsgo)
- Audit your current TypeScript version and all packages that depend on the compiler API (
ts-loader,ts-node,ts-morph, etc.). - Install the
@typescript/nativepackage from npm alongside your existingtypescriptpackage, pinned to an exact RC version. - Delete all stale
.tsbuildinfofiles, since the Go compiler's incremental artifacts are incompatible with the JS compiler's. - Run
tsgo --noEmitagainst your project and compare diagnostic codes withtscoutput to catch behavioral divergences. - Update
tsconfig.jsonby removingpreserveConstEnumsand noting unported features likedeclarationMap. - Adjust build scripts and CI pipelines to invoke
tsgofor type-checking while keepingtscas a parallel safety net. - Configure your editor (VS Code TypeScript Native Preview extension) to use the Go-based language service.
- Validate by running both compilers in CI during a transition period before dropping the legacy
tscdependency.
Table of Contents
- What Changed Under the Hood: The Go-Based Compiler
- Pre-Migration Assessment
- Step-by-Step Migration Guide
- Handling Breaking Changes and Edge Cases
- Performance Benchmarks: What to Expect
- Migration Checklist
- Should You Migrate Now?
- Summary and Next Steps
What Changed Under the Hood: The Go-Based Compiler
Why the Rewrite Happened
The JavaScript-based TypeScript compiler had hit a performance ceiling that incremental optimizations could no longer meaningfully address. The single-threaded nature of the Node.js runtime meant that type-checking, the most computationally expensive phase of compilation, could not use modern multi-core processors. Large monorepos with thousands of files routinely faced build times measured in minutes, and the compiler consumed more memory as project file counts grew.
The Corsa project set out to solve this by rewriting the compiler in Go, targeting three goals: native concurrency for parallel type-checking, ~60-70% lower peak memory usage through Go's more efficient memory model (see benchmarks below), and faster raw execution by compiling to a native binary rather than interpreting JavaScript. Anders Hejlsberg announced the effort publicly in early 2025. The team shipped an alpha, then reached Release Candidate status. RC status means the TypeScript team considers the compiler feature-complete for its target scope and suitable for broader testing, though some features remain unported and behavioral edge cases are still being resolved. RC software should not gate production releases without a parallel tsc safety net.
The Corsa project set out to solve this by rewriting the compiler in Go, targeting three goals: native concurrency for parallel type-checking, ~60-70% lower peak memory usage through Go's more efficient memory model, and faster raw execution by compiling to a native binary rather than interpreting JavaScript.
Architectural Differences at a Glance
The old compiler ran as a Node.js process, executing JavaScript (transpiled from TypeScript source), constrained to a single thread for type-checking. The new compiler ships as a standalone native binary built from Go, capable of concurrent type-checking across multiple goroutines.
What stayed the same: TypeScript language semantics, the type system's behavior, and tsconfig.json compatibility. Existing TypeScript code does not need syntax changes. What changed: the distribution model shifted from an npm package containing JavaScript to a native binary (also installable via npm as a wrapper), and the Go rewrite does not expose the programmatic API that tools like ts-node and custom transformers relied on.
| Aspect | TypeScript 5.x/6.x | TypeScript 7.0 RC |
|---|---|---|
| CLI invocation | npx tsc | npx tsgo or standalone tsgo |
| Runtime | Node.js (JavaScript) | Native Go binary |
| Distribution | npm package (typescript) | npm wrapper (verify package name at typescript-go releases) + standalone binary |
| Type-checking | Single-threaded | Concurrent |
| Programmatic API | ts.createProgram(), etc. | Not available; language service protocol (likely LSP-based, confirm in official documentation) planned |
tsconfig.json | Fully supported | Fully compatible (with minor option changes) |
Pre-Migration Assessment
Checking Your Current Setup
Before migrating, catalog your exact TypeScript version, all packages that depend on it, and whether any tooling calls the TypeScript Compiler API programmatically. Dependencies like ts-loader, ts-node, ts-jest, and @typescript-eslint/parser each interact with TypeScript differently, and their compatibility with 7.0 RC varies.
{
"scripts": {
"audit:ts-deps": "npm ls typescript && npm ls | grep -E 'ts-loader|ts-node|ts-jest|typescript-eslint|ts-morph|ttypescript'"
}
}
For npm v7+, add --depth=Inf if needed: npm ls --depth=Inf typescript. Output format changed between npm v6 and v7+.
Running npm run audit:ts-deps surfaces every package in the dependency tree that directly or transitively depends on TypeScript, giving you a clear inventory of what needs verification.
Known Limitations in the RC
The RC does not yet support declaration map generation (--declarationMap). Complex composite project configurations with circular references may produce different behavior in project references. The --build mode (tsc -b) has gaps in multi-project orchestration scenarios. The plugin ecosystem that relied on the JavaScript-based compiler API has no direct equivalent. Editor integration through the language service works in VS Code via an updated extension, but JetBrains has not announced a tsgo integration date as of mid-2025.
Step-by-Step Migration Guide
Step 1: Installing TypeScript 7.0 RC
The compiler is available through npm or as a standalone binary download. Verify the exact npm package name and binary download URLs at the typescript-go releases page before installing, as these may change before stable release.
# Install via npm (adds tsgo binary to node_modules/.bin)
# ⚠️ Verify the package name at https://github.com/microsoft/typescript-go/releases before running.
# Pin to a specific version for reproducible installs.
# Replace <exact-version> with the version from the releases page (e.g., 7.0.0-rc.1):
VERSION="<exact-version>" # ⚠️ You MUST replace this placeholder before running
npm install --save-dev @typescript/native@"$VERSION"
# Verify installation
npx tsgo --version
For the standalone binary, always verify the SHA-256 checksum of downloaded binaries against the value published on the official releases page before executing them. Do not run binaries downloaded without checksum verification.
# Standalone binary (macOS arm64 example — check the releases page for your OS/architecture)
curl --proto '=https' --tlsv1.2 -fsSL \
https://typescript.azureedge.net/releases/7.0.0-rc/tsgo-darwin-arm64 \
-o /usr/local/bin/tsgo
# Verify checksum — abort if mismatch (replace EXPECTED_SHA256 with value from releases page)
EXPECTED_SHA256="<replace-with-value-from-releases-page>"
ACTUAL_SHA256=$(shasum -a 256 /usr/local/bin/tsgo | awk '{print $1}')
if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then
echo "ERROR: Checksum mismatch. Expected: $EXPECTED_SHA256 Got: $ACTUAL_SHA256" >&2
rm -f /usr/local/bin/tsgo
exit 1
fi
chmod +x /usr/local/bin/tsgo
tsgo --version
The standalone binary URL shown is for macOS arm64. Verify the correct URL for your OS and architecture (Linux x86_64, Windows, etc.) on the releases page.
To run alongside an existing TypeScript 5.x or 6.x installation, keep the typescript package in devDependencies and add the Go-based package separately. Both binaries land in node_modules/.bin, so you can run them side by side.
Step 2: Running Your First Build with tsgo
Point the new compiler at an existing project by running tsgo in the project root. It reads the same tsconfig.json automatically.
# Old compiler
$ npx tsc --diagnostics
Files: 387
Lines: 94521
Nodes: 412893
Total time: 12.4s
# New compiler, same project
$ npx tsgo --diagnostics
Files: 387
Lines: 94521
Nodes: 412893
Total time: 1.3s
The diagnostics output format differs slightly. Error messages use the same diagnostic codes but wording differs; diagnostic codes remain identical, so match on codes, not message text. The --diagnostics flag works in both compilers, making side-by-side comparison easy.
Step 3: Updating tsconfig.json
Most tsconfig.json files work without changes. However, a few options warrant attention.
{
"compilerOptions": {
// Unchanged — these work identically in 7.0 RC
"target": "ES2022",
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "./dist",
// Still supported but limited in RC:
"declarationMap": true, // ⚠️ RC generates .d.ts files normally but does NOT generate .d.ts.map files. IDE go-to-definition for library consumers will be affected.
// Parallel type-checking is on by default; no tsconfig flag is required.
// See release notes for future opt-in options.
// Remove if present — no longer recognized:
// "preserveConstEnums" is removed. The Go compiler always emits const enum
// declarations in output (equivalent to the old preserveConstEnums: true).
// If your code relied on const enum *inlining* (the default
// preserveConstEnums: false behavior), test your JS runtime output carefully.
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
The strict flag and all its constituent flags (strictNullChecks, strictFunctionTypes, etc.) behave identically. The Go compiler drops the preserveConstEnums option because it always emits const enum declarations in output (equivalent to the old preserveConstEnums: true). If your build relied on const enum inlining across module boundaries (the default behavior when preserveConstEnums was false), this is a behavioral change. Test your runtime JS output carefully.
Step 4: Adapting Your Build Pipeline
Projects using bundlers feel this change only in the type-checking step, not transpilation. Tools like esbuild, Vite, and SWC handle their own transpilation and only invoke TypeScript for type-checking.
Delete stale incremental artifacts before the first tsgo run. The Go compiler's .tsbuildinfo files are not compatible with those from the JS compiler:
# Preview first (dry run — review the list before deleting)
find . \
-maxdepth 5 \
-name '*.tsbuildinfo' \
-not -path '*/node_modules/*' \
-print
# Execute only after confirming output above is correct
find . \
-maxdepth 5 \
-name '*.tsbuildinfo' \
-not -path '*/node_modules/*' \
-delete
{
"scripts": {
"typecheck": "tsgo --noEmit",
"typecheck:legacy": "tsc --noEmit",
"typecheck:compare": "time npm run typecheck:legacy; time npm run typecheck",
"build": "tsgo --noEmit && vite build",
"watch": "tsgo --watch --noEmit",
"lint": "eslint . --ext .ts,.tsx",
"ci:typecheck": "tsgo --noEmit --diagnostics"
}
}
The "build" script above uses tsgo --noEmit for type-checking only before handing off to Vite for transpilation and bundling. Omit --noEmit only if you intend tsgo to emit JS output directly. The "typecheck:compare" script uses ; instead of && so that tsgo timing runs even if tsc exits non-zero due to type errors.
CI/CD pipelines benefit because the native binary eliminates the Node.js runtime dependency for type-checking. CI images can shrink only if you use the standalone binary and no other Node.js tooling remains required. The binary must match the CI runner's OS and architecture. Cache the tsgo binary alongside node_modules, and delete any stale .tsbuildinfo files when switching compilers, since the Go compiler's incremental artifacts are incompatible with those from the JS compiler.
ts-loader users: the loader's transpileOnly: true mode continues to work since it bypasses type-checking entirely. ts-loader's full type-check mode calls the JS compiler API, which tsgo does not expose. Verify compatibility with your specific ts-loader version.
Step 5: Updating Editor and IDE Configuration
In VS Code, the TypeScript team provides an updated extension that uses the Go-based language service. Search for the TypeScript Native Preview extension on the VS Code Marketplace (verify the current extension name, as it may differ between releases), then configure your .vscode/settings.json:
{
"typescript.tsserver.useTsgo": true
}
Verify this setting key against the extension's README; it may differ between extension versions. If VS Code shows a yellow warning on the setting or the key does not appear in the Settings UI search, consult the extension documentation for the correct configuration.
JetBrains IDEs (WebStorm, IntelliJ IDEA) do not yet offer native tsgo language service integration as of the RC. These IDEs continue to use the JavaScript-based language service. Teams using JetBrains can still run tsgo for command-line type-checking while relying on the bundled TypeScript service for editor features.
Handling Breaking Changes and Edge Cases
Behavioral Differences to Watch For
The Go compiler produces identical type errors for the vast majority of code, but the RC has known divergences in narrowing behavior within complex conditional type patterns. The Go type resolver evaluates some deeply nested conditional types with infer clauses in a different order, which can change resolution results.
Error message wording differs in many cases. The diagnostic codes remain the same (e.g., TS2322 for type assignment errors), but the explanatory text may be phrased differently. Any tooling that parses error message text rather than diagnostic codes will need updates.
To report discrepancies, the TypeScript team tracks behavioral differences on the microsoft/typescript-go GitHub repository. Search for issues tagged with divergence-related labels (verify current label names at the repository). Running both compilers in parallel during a validation period is strongly recommended. A simple CI step can enforce this:
npx tsc --noEmit 2> legacy-errors.txt
npx tsgo --noEmit 2> native-errors.txt
# Compare code+count pairs so frequency differences are visible
diff \
<(grep -oE 'TS[0-9]+' legacy-errors.txt | sort | uniq -c | sort -k2) \
<(grep -oE 'TS[0-9]+' native-errors.txt | sort | uniq -c | sort -k2)
Programmatic API Migration
The TypeScript Compiler API (ts.createProgram, ts.createSourceFile, ts.forEachChild, etc.) does not exist in the Go rewrite. Tools built on this API, including ts-morph, custom AST transformers, and code generation pipelines, cannot use tsgo as a drop-in replacement.
The TypeScript team has outlined plans for a language service protocol that external tools can communicate with over IPC, but the team has not finalized this protocol in the RC. For now, projects relying on the programmatic API should continue using the JavaScript-based typescript package for those specific tasks while using tsgo for build-time type-checking.
The TypeScript Compiler API (
ts.createProgram,ts.createSourceFile,ts.forEachChild, etc.) does not exist in the Go rewrite. Tools built on this API, including ts-morph, custom AST transformers, and code generation pipelines, cannot usetsgoas a drop-in replacement.
// Old approach (TypeScript 5.x JS API) — still works with 'typescript' npm package
import * as ts from "typescript";
const program = ts.createProgram(["src/index.ts"], { strict: true });
// Check for program-level configuration errors before proceeding
const configDiagnostics = program.getConfigFileParsingDiagnostics();
if (configDiagnostics.length > 0) {
configDiagnostics.forEach(d =>
console.error("Config error:", ts.flattenDiagnosticMessageText(d.messageText, "
"))
);
process.exitCode = 1;
} else {
const diagnostics = ts.getPreEmitDiagnostics(program);
console.log(diagnostics.length, "errors found");
}
// TypeScript 7.0 RC alternative — invoke tsgo as a subprocess
import { spawnSync } from "child_process";
// Match diagnostic codes in compiler output (colon suffix avoids false positives)
const TS_ERROR_PATTERN = /error TS\d+:/g;
const MAX_OUTPUT_BYTES = 10 * 1024 * 1024; // 10 MB
const proc = spawnSync(
"tsgo",
["--noEmit", "--pretty", "false"], // verify flag support via: tsgo --help
{
encoding: "utf-8",
maxBuffer: MAX_OUTPUT_BYTES,
shell: false, // never use shell: true with interpolated args
}
);
if (proc.error) {
throw new Error(`Failed to spawn tsgo: ${proc.error.message}`);
}
// Diagnostics may appear on stdout or stderr; check both
const output = (proc.stdout ?? "") + (proc.stderr ?? "");
const errorCount = (output.match(TS_ERROR_PATTERN) ?? []).length;
console.log(errorCount, "errors found");
// Surface non-zero exit separately from error count
if (proc.status !== 0 && errorCount === 0) {
console.error("tsgo exited with status", proc.status, "— possible compiler crash");
process.exitCode = proc.status ?? 1;
}
Verify that tsgo supports the --pretty false flag by checking tsgo --help. stdout and stderr are captured separately to avoid conflating compiler diagnostics with runtime errors.
Performance Benchmarks: What to Expect
Real-World Build Time Comparisons
The TypeScript team published benchmarks alongside the RC announcement (source URL and hardware specification should be confirmed against the official TypeScript blog or microsoft/typescript-go repository). The following figures are presented as reported; independent verification requires reproducing on matching hardware.
| Project Size | TypeScript 5.8 | TypeScript 7.0 RC | Speedup | Memory (5.8) | Memory (7.0 RC) |
|---|---|---|---|---|---|
| Small (~50 files) | 2.1s | 0.4s | ~5x | 180 MB | 85 MB |
| Medium (~500 files) | 11.8s | 1.4s | ~8x | 620 MB | 210 MB |
| Large monorepo (~5,000+ files) | 68s | 7.2s | ~9.4x | 2.8 GB | 890 MB |
Note: Compared against TypeScript 5.8, the latest stable version at time of measurement. Benchmark results vary with hardware, OS, Node.js version, and project structure.
Watch mode responsiveness also improves: cold start for tsgo --watch is under 200ms compared to over 1 second for tsc --watch on the same hardware (exact figures depend on machine specifications). Incremental rebuilds after single-file changes drop to near-instant in small and medium projects.
Migration Checklist
Phase 1: Assessment
- Audit current TypeScript version and all dependent packages
- Review known RC limitations against project feature usage (declaration maps,
--buildmode, project references) - Verify the correct npm package name and version at the typescript-go releases page
Phase 2: Installation and Configuration
- Install TypeScript 7.0 RC alongside existing version, pinned to a specific version
- Delete stale
.tsbuildinfofiles before the firsttsgorun - Run
tsgo --noEmitagainst project and compare diagnostic output withtsc - Update
tsconfig.jsonfor removed options (preserveConstEnums) and unported features (declarationMap)
Phase 3: Build Pipeline and Tooling
- Adjust build scripts and CI/CD pipelines to use
tsgo - Cache native binary in CI and ensure OS/architecture match
- Update VS Code settings for native language service (verify setting key against extension documentation)
- Validate all programmatic API usage and migrate to subprocess invocation or retain JS compiler for those paths
Phase 4: Validation and Rollout
- Run full test suite and compare results between both compilers
- Benchmark build times with
--diagnosticsand document improvements - Set up parallel compiler runs in CI for validation period
- Plan timeline for dropping legacy
tscdependency after stable release
Should You Migrate Now?
When to Adopt the RC Today
Teams whose CI type-check exceeds roughly 10 seconds (around 500+ files) stand to gain the most. A 9x improvement on a 68-second build translates directly into faster feedback loops.
Greenfield projects with no Compiler API dependencies face the fewest migration risks. Teams already comfortable running RC software in development, with the JavaScript compiler as a fallback in production CI, can begin extracting value immediately. Do not use the RC compiler to gate production releases without a parallel tsc safety net.
Teams whose CI type-check exceeds roughly 10 seconds (around 500+ files) stand to gain the most. A 9x improvement on a 68-second build translates directly into faster feedback loops.
When to Wait for Stable
- Your project depends on the TypeScript Compiler API for code generation, custom lint rules, or AST transformers, and needs that API to work against the same compiler binary.
- You use
--buildmode for complex multi-project workspaces and cannot tolerate orchestration gaps. - Your environment is risk-averse, and a compiler behavioral divergence could cause production issues. Wait for the stable release, when the divergence issue tracker shows resolution of known differences.
Summary and Next Steps
Migrating from the JavaScript-based TypeScript compiler to the Go-based tsgo requires fewer than five configuration changes for projects that use TypeScript for type-checking and emit without relying on the programmatic API. Verify the current package name at the typescript-go releases page, install it, run tsgo alongside tsc, compare diagnostics, update configurations, and adjust build pipelines. The programmatic API gap is the most significant blocker for tool-heavy projects.
The official TypeScript 7.0 RC release notes and migration documentation are available on the TypeScript blog and the microsoft/typescript-go GitHub repository. Test in non-production environments and report divergences through the repository's issue tracker to help the team reach a stable release.

