- Introduction — July 8: tsgo Just Became tsc
- Getting the Numbers Right — What Was Actually Measured
- The "10x" Has a Dial — --checkers
- The Real Cost (1) — Everything TypeScript 6 Deprecated Is Now a Hard Error
- The Real Cost (2) — No API, So Vue, MDX, Astro, and Svelte Cannot Move Today
- Running 6 and 7 Side by Side — tsc6 and npm Aliases
- Quietly Changed — JSDoc and Unicode
- So, Should You Move Today?
- Closing
- References
Introduction — July 8: tsgo Just Became tsc
On July 8, 2026, TypeScript 7.0 went GA. The Go native port, which had been running in preview for over 1 year, landed in a full release.
If you have followed this project over the past 1 year, the name tsgo will be familiar. Nightlies shipped as a separate binary from a separate package (@typescript/native-preview), and running it side by side with the existing tsc was the standard procedure. That arrangement is gone at GA. The word tsgo does not appear once in the official announcement. Instead, it says that running npm install -D typescript gets you "a new tsc executable."
In other words, the native port is not opt-in anymore — it is the default. Checking the npm registry directly, the latest tag for typescript is 7.0.2, published on 2026-07-08 — exactly matching the GA date in the announcement. And the last publish of @typescript/native-preview stopped at July 7, one day before GA. Nightlies have now moved to typescript@next (currently in the 7.1.0-dev line).
The release timeline ran as follows: beta on April 21, RC on June 18, GA on July 8.
This post is not here to re-explain that "the Go port is fast." That was already covered in TypeScript 6 and the tsc-go Port, back in the preview era, and honestly, the shipping shape we expected back then — a backend flag like tsc --go, one major version shipping two compilers side by side — is not what GA turned out to be. What actually happened is that the major version itself split — 6 is the JS implementation, 7 is the Go implementation. This post sticks to what is confirmed at GA and looks at the real migration costs the headline number hides.
Getting the Numbers Right — What Was Actually Measured
The announcement's own phrase is "10x faster native port," and the qualified sentence in the body reads: native code speed, shared-memory multithreading, and various optimizations typically produce an 8x to 12x speedup on full builds.
Here is the full-build timing table Microsoft measured and published directly. This is a vendor-reported figure, measured on the same machine using TypeScript 7's default settings.
Codebase TS 6 TS 7 Speedup
vscode 125.7s 10.6s 11.9x
sentry 139.8s 15.7s 8.9x
bluesky 24.3s 2.8s 8.7x
playwright 12.8s 1.47s 8.7x
tldraw 11.2s 1.46s 7.7x
Two things stand out. First, the table's low end is 7.7x, slightly below the announcement's own "8-12x" claim. Second, the speedup varies by codebase — vscode's 11.9x and tldraw's 7.7x are 1.5x apart. Larger codebases appear to see bigger parallelization gains.
Memory numbers were published alongside these, and this is actually where you should temper expectations.
Codebase TS 6 TS 7 Change
vscode 5.2GB 4.2GB -18%
sentry 4.9GB 4.6GB -6%
bluesky 1.8GB 1.3GB -26%
playwright 1.0GB 0.9GB -11%
tldraw 0.6GB 0.5GB -15%
This is not the "half the memory" story that circulated during preview. The actual GA figures show a 6% to 26% reduction, and sentry is essentially flat. Compared to speed jumping by a single-digit multiplier, memory is a modest improvement. The announcement itself only claims that it "typically requires less total memory across full builds," and does not claim more than that.
There are editor-side numbers too. For the VS Code codebase, the time to see the first error after opening a file with an error, on the same machine, used to take about 17.5 seconds; on TypeScript 7 it is under 1.3 seconds — more than a 13x speedup.
Numbers reported from enterprise case studies need to be read with an extra degree of caution. These are figures Microsoft says it heard secondhand from each team.
- Slack — CI type-check time went from about 7.5 minutes to 1.25 minutes. Reportedly, 40% of merge-queue time disappeared. Previously, editor language-server load times made local development nearly "unusable," so engineers offloaded full type checking to CI; now the same codebase reportedly loads in seconds.
- Canva — time to see the first error in the editor went from about 58 seconds to about 4.8 seconds.
- Vanta — up to 9x on its single largest project.
- The Microsoft News Services team — saved 400 hours a month that used to go into waiting on CI builds.
There is also a stability figure. Based on its own data insights, Microsoft says 7.0's new language server cut failed language-server commands by over 80% and server crashes by over 60%, compared to 6.0. This is a telemetry-based self-measurement and not the kind of figure an outsider can reproduce.
The "10x" Has a Dial — --checkers
This is the part that only came out at GA, and that most summary articles skip. Those benchmark numbers are the result of one specific parallelization setting.
TypeScript 7.0 runs parsing, type checking, and emitting in parallel. Parsing and emitting are nearly independent per file, so they parallelize well. The problem is type checking — cross-file dependencies are complex, and most files lean on the same global scope and the same dependencies' type information. On top of that, type checking sometimes depends on the relative order of information within the program, so keeping results consistent requires always checking in the same order.
So TypeScript 7 spins up a fixed number of type-checker workers. Each worker keeps its own view of the world and duplicates some shared work, but for the same input it always splits files the same way and produces the same result.
The default worker count is 4. The tables above were all measured with the default --checkers 4, and the announcement runs a second table on the same machines with --checkers 8.
Codebase TS 6 TS 7 (--checkers 8) Speedup
vscode 125.7s 7.51s 16.7x
sentry 139.8s 12.08s 11.6x
bluesky 24.3s 2.01s 12.1x
playwright 12.8s 1.16s 11x
tldraw 11.2s 1.06s 10.6x
Bumping checkers to 8 takes vscode as high as 16.7x. But it is not free — in the announcement's own words, raising the checker count typically comes at the cost of increased memory usage. And results vary by project and machine.
It goes the other direction too. In environments with fewer CPU cores and less memory — the announcement's own example is a CI runner — it can actually be better to lower this value to avoid unnecessary overhead. You can set it as low as --checkers 1, at which point type checking becomes effectively single-threaded and the duplicated work disappears.
Here comes the single most practically important sentence.
In rare cases, changing the
--checkerscount can surface order-dependent results.
In other words, the team is directly admitting that the checker count can affect diagnostic results. The announcement's recommendation is to pin a fixed checker count across your whole build environment so everyone gets the same result, while adding that it is ultimately up to the team. If you leave it inconsistent — 8 locally, 2 in CI, say — that opens the door, in principle, to a "passes on my machine, errors in CI" situation. Personally, I would nail this down in one place, whether that is tsconfig.json or a CI script.
There are two more related flags. --builders controls how many project-reference builders run concurrently in --build mode (for monorepos). The thing to watch is that it multiplies with --checkers — straight from the announcement's own example, --checkers 4 --builders 4 allows up to 16 type checkers running concurrently, which can be excessive. --singleThreaded turns off parallelization entirely (for debugging, comparing 6 vs 7 performance, cases where an external tool orchestrates parallel builds, or very resource-constrained environments). --checkers and --builders are currently introduced as experimental flags.
Unlike --checkers, --builders is explicitly documented to not change results when its count changes. Instead, project-reference builds are fundamentally bottlenecked by the project dependency graph.
The Real Cost (1) — Everything TypeScript 6 Deprecated Is Now a Hard Error
Now for the part where you pay.
Compatibility itself is good. The announcement's qualified sentence reads: with the stableTypeOrdering flag on and the ignoreDeprecations flag unset, virtually anything that compiles cleanly under TypeScript 6.0 should compile identically under 7.0.
The problem is that premise. 7.0 adopts 6.0's new defaults wholesale, and turns flags and syntax that 6.0 flagged as deprecated into hard errors. As the announcement itself concedes, "6.0 is relatively new, and many projects still need to adapt to its new behavior." So the official recommendation is not to jump straight to 7, but to adopt 6.0 first to ease the transition.
Let us start with the default changes.
strict -> defaults to true
module -> defaults to esnext
target -> the latest stable ECMAScript version just before esnext
noUncheckedSideEffectImports -> defaults to true
libReplacement -> defaults to false
stableTypeOrdering -> defaults to true, and cannot be turned off
rootDir -> defaults to ./ (an inner source directory must be specified explicitly)
types -> defaults to [] (the old behavior was ["*"])
The two changes the announcement calls out as the "most surprising" are rootDir and types. Both are easy to work around. Projects whose tsconfig.json sits outside a directory like src can just set rootDir explicitly to preserve their directory structure.
{
"compilerOptions": {
"rootDir": "./src"
},
"include": ["./src"]
}
For types, projects that rely on global declarations now have to list what they need explicitly.
{
"compilerOptions": {
"types": ["node", "jest"]
}
}
This looks harmless, but it is a quiet landmine. Once types defaults to [], automatic discovery turns off — if you had been relying on installing @types/node or @types/jest and having them picked up automatically, 7 suddenly floods you with errors about missing global symbols. The code is not wrong, the configuration changed, and the fix is a one-liner — but walking through this package by package in a large monorepo is tedious work.
strict defaulting to true is the same story. For a legacy codebase that has lived non-strict up to now, this is not "swapping compilers" — it is "rewriting your types." You could end up paying months of strictNullChecks work up front just to get an 8x-faster compiler.
And then there are the things that are simply gone — not no-ops, hard errors.
- Support for
target: es5ends - Support for
downlevelIterationends - Support for
moduleResolution: nodeandnode10ends (nodenextorbundlerrecommended) - Support for
module: amd,umd,systemjs, andnoneends (esnextorpreserverecommended) - Support for
baseUrlends (updatepathsto be relative to the project root) - Support for
moduleResolution: classicends esModuleInteropandallowSyntheticDefaultImportscan no longer be set tofalsealwaysStrictis always treated as true and can no longer be set tofalse- The
modulekeyword can no longer be used in namespace declarations - The
assertskeyword can no longer be used on imports — usewithinstead, matching ECMAScript import attributes syntax - Under
skipDefaultLibCheck, the/// <reference no-default-lib />directive is no longer honored - If a
tsconfig.jsonexists in the current directory, command-line builds can no longer accept file paths (unless you pass--ignoreConfigexplicitly)
The two items on this list that will hurt the most in practice are baseUrl and target: es5. baseUrl is baked broadly into absolute-path imports in older projects, and target: es5 can be a non-negotiable requirement for teams that still have to support legacy browsers. If you need es5, 7 is not for you. This is not the kind of wall you can configure your way past.
That last item is also surprisingly easy to trip over. Plenty of teams have something like npx tsc src/foo.ts baked into a script, and if there is a tsconfig.json at the project root, that is now simply an error.
The Real Cost (2) — No API, So Vue, MDX, Astro, and Svelte Cannot Move Today
This is the most important part of the GA announcement, and the least-quoted.
TypeScript 7.0 is here, but it ships no API.
There is no programming API. The announcement says a new (and different) API is expected to ship in 7.1, and that until then, the priority was making it possible to run 6 and 7 side by side.
The fallout is direct. Carrying over the announcement's "TypeScript and Embedded Languages" section verbatim: workflows using Vue, MDX, Astro, Svelte, and similar tools are likely unable to take advantage of TypeScript 7 yet. The same goes for specialized in-template type checking like Angular's. The reason is that 7 does not yet expose a stable programming API, so tools that embed TypeScript in their own compilers and language services — like Volar — can currently only depend on TypeScript 6.0.
This is not "might be a bit slow" — it is cannot use it. A substantial share of the frontend ecosystem is caught here. The Vue team, the Astro team, the Svelte team, and every MDX-based docs/blog pipeline all sit on top of Volar.
The recommendations split three ways.
- Use 7 in scenarios that do not need a language-server plugin — this is the default recommendation.
- Angular — you can combine fast project-wide error detection via
tscin the CLI with editor support running on 6.0. In other words, you can take half the win. - Vue, MDX, Astro, Svelte, and the like — you have to keep using 6.0 for now. In VS Code, the "Disable TypeScript 7 Language Server" command reverts you to 6.0.
Microsoft frames this as a "point-in-time issue," has promised a fix, and says it will work actively with the maintainers of the affected projects. I take that as a credible commitment — but a commitment does not fix today's build. It will take several release cycles before 7.1's new API ships, Volar ports to it, and Vue/Astro/Svelte tooling each adopts it in turn. The announcement itself states a release cadence of every 3 to 4 months, and downstream adoption time stacks on top of that.
Running 6 and 7 Side by Side — tsc6 and npm Aliases
So the realistic answer is usually "keep both." Microsoft shipped a new compatibility package for exactly this.
@typescript/typescript6 provides an executable named tsc6. That lets you install it side by side with 7.0 — which brings its own tsc binary — without a naming collision. The package also re-exports the TypeScript 6.0 API, so you can run tsc on 7 while keeping other tooling dependent on 6.0. Checking the npm registry, this package's latest is 6.0.2 and its bin entry is exactly one: tsc6.
Tools like typescript-eslint expect to import directly from typescript via a peer dependency, so the recommended approach is an npm alias.
npm install -D typescript@npm:@typescript/typescript6
But doing only that leaves you with just the tsc6 executable. To also get 7.0's tsc, add one more alias.
{
"devDependencies": {
"@typescript/native": "npm:typescript@^7.0.2",
"typescript": "npm:@typescript/typescript6@^6.0.2"
}
}
With this, npx tsc runs on 7.0, while tools that import typescript see 6.0.
Honestly, this is not an elegant solution. Two intertwined aliases in package.json, with the name typescript actually pointing at 6 — that is genuinely confusing to anyone seeing it for the first time. But if you use typescript-eslint and still want tsc to run fast — which describes a good chunk of real-world projects — this is the official path for now.
Quietly Changed — JSDoc and Unicode
Two more changes are overshadowed by the performance headlines but can actually break code.
JavaScript support was reworked. TypeScript originally supported JS files by recognizing JSDoc comments and specific code patterns, which was often a pile of special cases based on what Closure or JSDoc documentation-generation tools understood. 7.0 rewrote this to be consistent with how .ts files are analyzed. As a result, some things went away.
- You can no longer write a value where a type is expected — use
typeof someValueinstead @enumis no longer given special treatment- A bare
?can no longer be used as a type — useany @classno longer turns a function into a constructor — use a class declaration- Trailing
!is no longer supported - Type names must be defined inside the
@typedeftag (placing them next to an identifier is no longer allowed) - Closure-style function syntax is no longer supported — use the TypeScript shorthand
Patterns like aliasing this or wholesale reassigning a function's prototype have also lost their special treatment. If you have a large JS codebase typed with JSDoc, this is where the real migration work is. The TypeScript team says it maintains a separate CHANGES.md file capturing the differences between 6.0 and 7.0, and describes JS support as still "in flux."
Template literal types now preserve Unicode code points.
type HeadTail<S> = S extends `${infer Head}${infer Tail}` ? [Head, Tail] : never;
type Result = HeadTail<"😀abc">;
// On TS 7.0: ["😀", "abc"]
// Before: ["\ud83d", "\ude00abc"]
Previously, following JavaScript's UTF-16 indexing behavior, surrogate pairs were split in half. That was technically consistent with JS indexing, but usually not what anyone intended, and it could produce string literal types holding meaningless unpaired surrogates. The new behavior matches the intuition you get from iterating with for...of or spreading.
The announcement honestly labels this as a breaking change for type-level string manipulation that deliberately models UTF-16 code units — some string Length utilities are given as an example. If you use or build libraries that do heavy type-level string programming, you need to check this.
One more thing. --watch mode has been completely rebuilt. The new foundation is a Go port of the Parcel bundler's file watcher (it was originally C++, requiring a whole C++ toolchain, and has been moved to Go with a minimal assembly shim). The reason is that the Go standard library has no file-watching API, and a polling-based solution was too expensive for large projects with heavy node_modules dependencies. The announcement reports significantly improved resource usage for --watch across platforms.
So, Should You Move Today?
Here is how it breaks down.
When moving today pays off
- You are already on TypeScript 6.0 and build cleanly with
stableTypeOrderingon and noignoreDeprecations— this is exactly the condition the official compatibility statement guarantees. In this case, migration is generally painless. - Your codebase is pure
.ts/.tsxand does not use Volar-family embedded-language tooling. - CI type checking is a real bottleneck — the 8x pays off directly here.
- Editor responsiveness is a real pain point for your team.
When you cannot move yet
- You use Vue, MDX, Astro, or Svelte — this is not a matter of choice. You have to wait for 7.1's API and the Volar port that follows it.
- Angular — only half of it is possible. CLI type checking on 7, editor on 6.
- You need
target: es5— this is a wall. - You are still on TypeScript 5.x and non-strict — do not jump straight to 7. Going through 6 first is the official recommendation, and there is a reason for it: instead of hitting the entire deprecation list at once, you can work through it as warnings under 6.
- API-dependent tooling like typescript-eslint is core to your workflow — the alias combination above makes it possible, but whether that complexity is worth taking on is a call your team has to make.
One piece of sequencing advice. If you do move, start by explicitly pinning your --checkers value. If local and CI run at different default parallelism levels and you run into an order-dependent diagnostic difference, that is the exact kind of bug nobody wants to debug. Given that the team has written, in its own words, that it "can surface in rare cases," pinning the value costs one line, and not pinning it costs half a day.
Closing
TypeScript 7.0's performance story is real. It is vendor self-reported, but it was measured against reproducible open-source codebases, the conditions (default --checkers 4, full builds) are disclosed, and the announcement even ran a --checkers 8 table alongside it, which itself reveals that the numbers move with configuration. As vendor benchmarks go, this is on the honest end. If numbers like Slack's 7.5 minutes to 1.25 minutes reproduce, that is a quality-of-life issue on a large codebase.
But the headline is "10x faster," and the real story is "10x faster, at the cost of clearing 6's entire deprecation list, with a large piece of the frontend ecosystem not invited until the API ships."
So here is how I see it — 7.0 is a migration that has started, not one that is finished. Until 7.1 ships with an API and Volar builds on top of it, this ecosystem lives split between 6 and 7 for a while. The very existence of compatibility packages like @typescript/typescript6 and tsc6 is an admission of that. Microsoft knows it too, which is why the announcement closes by saying it wants to "close whatever gaps remain with 7.1 and bring the community forward."
If you have a pure TS codebase, today is a good day. If you are standing on Vue or Astro, this release is not yours yet — and that is not because you did anything wrong.
References
- Announcing TypeScript 7.0 (Microsoft, 2026-07-08) — source for every figure and quote in this post
- Announcing TypeScript 7.0 RC (2026-06-18)
- Announcing TypeScript 7.0 Beta (2026-04-21)
- npm — typescript — at GA,
latestis 7.0.2,nextis in the 7.1.0-dev line - npm — @typescript/typescript6 — the 6.0 compatibility package providing the
tsc6executable - microsoft/typescript-go — the native port repository
- TypeScript 6 and the tsc-go Port — related post, from the preview era
현재 단락 (1/151)
On July 8, 2026, [TypeScript 7.0 went GA](https://devblogs.microsoft.com/typescript/announcing-types...