Which project does this relate to?
Router
Describe the bug
A regression in the TypeScript 7 native compiler (@typescript/native-preview / tsgo), starting in 7.0.0-dev.20260624.1, makes valid TanStack Router code fail type-checking.
A route's resolved search schema is the intersection of its parent's search schema and the route's own validateSearch output. When that schema is used as a type argument — e.g. for the stripSearchParams search middleware — tsgo drops the route's own member from the intersection, leaving only the parent's. The middleware, correctly typed SearchMiddleware<Parent & Own>, is then checked against SearchMiddleware<Parent> and rejected with TS2322.
This is not a Router defect — the types are valid. Stable tsc (6.0.3) and tsgo 7.0.0-dev.20260623.1 both accept the exact same code; only tsgo >= 20260624.1 rejects it. Filing here because it breaks Router users who run the native-preview compiler, and you may want to track it or add a type-level workaround. Root cause is upstream and appears related to microsoft/typescript-go#4391 (also router-core, same build window, different surface — there a const type parameter loses a string-literal through Omit<...>, surfacing as TS2353).
Version matrix (same code, only the compiler changes)
| Compiler |
Result |
stable tsc 6.0.3 |
no errors |
tsgo 7.0.0-dev.20260623.1 |
no errors |
tsgo 7.0.0-dev.20260624.1 (first bad) |
TS2322 |
tsgo 7.0.0-dev.20260627.2 (latest) |
TS2322 |
@tanstack/react-router@1.170.16, @tanstack/zod-adapter@1.167.0, zod@4.4.3, macOS arm64.
Actual error
src/routes/pricing.tsx(10,27): error TS2322: Type 'SearchMiddleware<{ billing: "monthly" | "yearly"; } & { page: number; }>' is not assignable to type 'SearchMiddleware<{ page: number; }>'.
The expected type has collapsed to the parent-only { page: number } — the route's own { billing } member is dropped from the intersection in this generic position.
Real-world impact
In a full app (root validateSearch + many file routes) the same root cause cascades widely: TS2322 on every stripSearchParams middleware, plus TS2339 on Route.useSearch().<ownField> and TS2353 on navigate({ search }) literals, because each route's resolved search schema falls back to the root-only schema. A mid-size app surfaced ~156 errors on 20260627.2, all clean on 20260623.1.
Your Example Website or App
Minimal reproduction (two route files) inlined below.
Steps to Reproduce the Bug or Issue
src/routes/__root.tsx — root validates a shared page param:
import { createRootRoute, Outlet } from '@tanstack/react-router';
import { zodValidator } from '@tanstack/zod-adapter';
import { z } from 'zod';
export const Route = createRootRoute({
validateSearch: zodValidator(z.object({ page: z.coerce.number().default(1) })),
component: () => <Outlet />,
});
src/routes/pricing.tsx — leaf adds billing + a stripSearchParams middleware:
import { createFileRoute, stripSearchParams } from '@tanstack/react-router';
import { zodValidator } from '@tanstack/zod-adapter';
import { z } from 'zod';
const defaults = { billing: 'monthly' } as const;
export const Route = createFileRoute('/pricing')({
validateSearch: zodValidator(z.object({ billing: z.enum(['monthly', 'yearly']).default('monthly') })),
search: { middlewares: [stripSearchParams(defaults)] },
component: Page,
});
function Page() {
return Route.useSearch().billing;
}
Then:
npm install
npx tsr generate # @tanstack/router-cli -> src/routeTree.gen.ts
npx tsgo --noEmit # TS2322 on tsgo >= 20260624.1
npx tsc --noEmit # clean (stable TypeScript)
Expected behavior
No error. The route's search schema is { page: number } & { billing: 'monthly' | 'yearly' }, and stripSearchParams({ billing: 'monthly' }) yields a SearchMiddleware for exactly that type — as stable tsc and tsgo 20260623.1 both confirm.
Screenshots or Videos
N/A
Platform
- TanStack Router: 1.170.16
- tsgo (
@typescript/native-preview): 7.0.0-dev.20260624.1+ (clean on 20260623.1)
- OS: macOS (arm64)
Additional context
Bisected to 7.0.0-dev.20260624.1. Likely the same upstream tsgo regression as microsoft/typescript-go#4391.
Which project does this relate to?
Router
Describe the bug
A regression in the TypeScript 7 native compiler (
@typescript/native-preview/ tsgo), starting in7.0.0-dev.20260624.1, makes valid TanStack Router code fail type-checking.A route's resolved search schema is the intersection of its parent's search schema and the route's own
validateSearchoutput. When that schema is used as a type argument — e.g. for thestripSearchParamssearch middleware — tsgo drops the route's own member from the intersection, leaving only the parent's. The middleware, correctly typedSearchMiddleware<Parent & Own>, is then checked againstSearchMiddleware<Parent>and rejected withTS2322.This is not a Router defect — the types are valid. Stable
tsc(6.0.3) and tsgo7.0.0-dev.20260623.1both accept the exact same code; only tsgo>= 20260624.1rejects it. Filing here because it breaks Router users who run the native-preview compiler, and you may want to track it or add a type-level workaround. Root cause is upstream and appears related to microsoft/typescript-go#4391 (also router-core, same build window, different surface — there aconsttype parameter loses a string-literal throughOmit<...>, surfacing asTS2353).Version matrix (same code, only the compiler changes)
tsc6.0.37.0.0-dev.20260623.17.0.0-dev.20260624.1(first bad)7.0.0-dev.20260627.2(latest)@tanstack/react-router@1.170.16,@tanstack/zod-adapter@1.167.0,zod@4.4.3, macOS arm64.Actual error
The expected type has collapsed to the parent-only
{ page: number }— the route's own{ billing }member is dropped from the intersection in this generic position.Real-world impact
In a full app (root
validateSearch+ many file routes) the same root cause cascades widely:TS2322on everystripSearchParamsmiddleware, plusTS2339onRoute.useSearch().<ownField>andTS2353onnavigate({ search })literals, because each route's resolved search schema falls back to the root-only schema. A mid-size app surfaced ~156 errors on20260627.2, all clean on20260623.1.Your Example Website or App
Minimal reproduction (two route files) inlined below.
Steps to Reproduce the Bug or Issue
src/routes/__root.tsx— root validates a sharedpageparam:src/routes/pricing.tsx— leaf addsbilling+ astripSearchParamsmiddleware:Then:
Expected behavior
No error. The route's search schema is
{ page: number } & { billing: 'monthly' | 'yearly' }, andstripSearchParams({ billing: 'monthly' })yields aSearchMiddlewarefor exactly that type — as stabletscand tsgo20260623.1both confirm.Screenshots or Videos
N/A
Platform
@typescript/native-preview): 7.0.0-dev.20260624.1+ (clean on 20260623.1)Additional context
Bisected to
7.0.0-dev.20260624.1. Likely the same upstream tsgo regression as microsoft/typescript-go#4391.