From 60d63821f2a3cc2b9f808da9467ee9618c83e198 Mon Sep 17 00:00:00 2001 From: Scott Street Date: Mon, 11 May 2026 19:36:47 +0300 Subject: [PATCH 1/4] fix(router-core): fix search middleware type to use schema output --- packages/router-core/src/route.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/router-core/src/route.ts b/packages/router-core/src/route.ts index b92401b652..27db7fc350 100644 --- a/packages/router-core/src/route.ts +++ b/packages/router-core/src/route.ts @@ -1274,9 +1274,7 @@ export interface UpdatableRouteOptions< preloadGcTime?: number search?: { middlewares?: Array< - SearchMiddleware< - ResolveFullSearchSchemaInput - > + SearchMiddleware> > } /** From 65df0629064429912e4893468cb42c73bd8469cc Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Fri, 5 Jun 2026 20:23:29 +0200 Subject: [PATCH 2/4] add type test --- .../tests/searchMiddleware.test-d.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 packages/router-core/tests/searchMiddleware.test-d.ts diff --git a/packages/router-core/tests/searchMiddleware.test-d.ts b/packages/router-core/tests/searchMiddleware.test-d.ts new file mode 100644 index 0000000000..30729b32b2 --- /dev/null +++ b/packages/router-core/tests/searchMiddleware.test-d.ts @@ -0,0 +1,39 @@ +import { describe, expectTypeOf, test } from 'vitest' +import { BaseRootRoute, BaseRoute, type ValidatorAdapter } from '../src' + +describe('search middlewares', () => { + test('should use search validator output for middleware context', () => { + type SearchInput = { + page?: string + } + + type SearchOutput = { + page: number + } + + const searchValidator: ValidatorAdapter = { + types: undefined as never, + parse: () => ({ page: 1 }), + } + + const rootRoute = new BaseRootRoute({}) + + new BaseRoute({ + getParentRoute: () => rootRoute, + path: '/posts', + validateSearch: searchValidator, + search: { + middlewares: [ + ({ search, next }) => { + expectTypeOf(search).toEqualTypeOf() + expectTypeOf(next).toBeCallableWith({ page: 2 }) + expectTypeOf(next).parameter(0).toEqualTypeOf() + expectTypeOf(next({ page: 2 })).toEqualTypeOf() + + return search + }, + ], + }, + }) + }) +}) From a40df235f280157ff8e78142ffc598e61e974704 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Fri, 5 Jun 2026 20:32:34 +0200 Subject: [PATCH 3/4] add changeset --- .changeset/quiet-plums-help.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/quiet-plums-help.md diff --git a/.changeset/quiet-plums-help.md b/.changeset/quiet-plums-help.md new file mode 100644 index 0000000000..f240c4fee7 --- /dev/null +++ b/.changeset/quiet-plums-help.md @@ -0,0 +1,5 @@ +--- +'@tanstack/router-core': patch +--- + +fix(router-core): use search validator output type for search middleware context From 84e83ce6563e5f12124f0f7b241dea722bf4ba21 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Fri, 5 Jun 2026 21:42:44 +0200 Subject: [PATCH 4/4] fix --- packages/router-core/src/searchMiddleware.ts | 4 +- .../tests/searchMiddleware.test-d.ts | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/packages/router-core/src/searchMiddleware.ts b/packages/router-core/src/searchMiddleware.ts index 1d60cc9587..212b41210f 100644 --- a/packages/router-core/src/searchMiddleware.ts +++ b/packages/router-core/src/searchMiddleware.ts @@ -45,9 +45,7 @@ export function retainSearchParams( export function stripSearchParams< TSearchSchema, TOptionalProps = PickOptional>, - const TValues = - | Partial> - | Array, + const TValues = Partial> | Array, const TInput = IsRequiredParams extends never ? TValues | true : TValues, diff --git a/packages/router-core/tests/searchMiddleware.test-d.ts b/packages/router-core/tests/searchMiddleware.test-d.ts index 30729b32b2..8f68d91b21 100644 --- a/packages/router-core/tests/searchMiddleware.test-d.ts +++ b/packages/router-core/tests/searchMiddleware.test-d.ts @@ -1,5 +1,10 @@ import { describe, expectTypeOf, test } from 'vitest' -import { BaseRootRoute, BaseRoute, type ValidatorAdapter } from '../src' +import { + BaseRootRoute, + BaseRoute, + stripSearchParams, + type ValidatorAdapter, +} from '../src' describe('search middlewares', () => { test('should use search validator output for middleware context', () => { @@ -36,4 +41,36 @@ describe('search middlewares', () => { }, }) }) + + test('should allow stripping default-valued validator output keys', () => { + type RootSearch = { + root?: string + } + + type SearchInput = { + foo?: string + } + + type SearchOutput = { + foo: string + } + + const searchValidator: ValidatorAdapter = { + types: undefined as never, + parse: () => ({ foo: 'default' }), + } + + const rootRoute = new BaseRootRoute({ + validateSearch: (search: RootSearch): RootSearch => search, + }) + + new BaseRoute({ + getParentRoute: () => rootRoute, + path: '/posts', + validateSearch: searchValidator, + search: { + middlewares: [stripSearchParams({ foo: 'default' })], + }, + }) + }) })