Skip to content

Commit 540d221

Browse files
fix: MatchRoute types (#7139)
Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com> Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
1 parent edb24b4 commit 540d221

6 files changed

Lines changed: 49 additions & 22 deletions

File tree

.changeset/fair-phones-grow.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@tanstack/react-router': patch
3+
'@tanstack/solid-router': patch
4+
'@tanstack/vue-router': patch
5+
---
6+
7+
Fix `MatchRoute` child callback param inference to resolve params from the target `to` route instead of the route path key across React, Solid, and Vue adapters.

packages/react-router/src/Matches.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,8 @@ import type {
2222
MakeRouteMatchUnion,
2323
MaskOptions,
2424
MatchRouteOptions,
25-
NoInfer,
2625
RegisteredRouter,
27-
ResolveRelativePath,
2826
ResolveRoute,
29-
RouteByPath,
3027
ToSubOptionsProps,
3128
} from '@tanstack/router-core'
3229

@@ -180,10 +177,9 @@ export type MakeMatchRouteOptions<
180177
// If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
181178
children?:
182179
| ((
183-
params?: RouteByPath<
184-
TRouter['routeTree'],
185-
ResolveRelativePath<TFrom, NoInfer<TTo>>
186-
>['types']['allParams'],
180+
params?: Expand<
181+
ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']
182+
>,
187183
) => React.ReactNode)
188184
| React.ReactNode
189185
}

packages/react-router/tests/Matches.test-d.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
useMatchRoute,
99
useMatches,
1010
} from '../src'
11-
import type { AnyRouteMatch, RouteMatch } from '../src'
11+
import type * as React from 'react'
12+
import type { AnyRouteMatch, MakeMatchRouteOptions, RouteMatch } from '../src'
1213

1314
const rootRoute = createRootRoute()
1415

@@ -233,3 +234,19 @@ test('when filtering useMatches by loaderData with an array', () => {
233234
matches.filter((match) => isMatch(match, 'loaderData.0.comment')),
234235
).toEqualTypeOf<Array<CommentsMatch>>()
235236
})
237+
238+
test('MatchRoute children are typed from resolved params under pathless layouts', () => {
239+
type CommentsMatchRouteChildren = MakeMatchRouteOptions<
240+
DefaultRouter,
241+
string,
242+
'/comments/$id'
243+
>['children']
244+
type CommentsMatchRouteRenderFn = Extract<
245+
CommentsMatchRouteChildren,
246+
(...args: Array<any>) => any
247+
>
248+
249+
expectTypeOf<CommentsMatchRouteRenderFn>().toEqualTypeOf<
250+
(params?: { id: string } | undefined) => React.ReactNode
251+
>()
252+
})

packages/solid-router/src/Matches.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@ import type {
1717
MakeRouteMatchUnion,
1818
MaskOptions,
1919
MatchRouteOptions,
20-
NoInfer,
2120
RegisteredRouter,
22-
ResolveRelativePath,
2321
ResolveRoute,
24-
RouteByPath,
2522
ToSubOptionsProps,
2623
} from '@tanstack/router-core'
2724

@@ -166,10 +163,9 @@ export type MakeMatchRouteOptions<
166163
// If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
167164
children?:
168165
| ((
169-
params?: RouteByPath<
170-
TRouter['routeTree'],
171-
ResolveRelativePath<TFrom, NoInfer<TTo>>
172-
>['types']['allParams'],
166+
params?: Expand<
167+
ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']
168+
>,
173169
) => Solid.JSX.Element)
174170
| Solid.JSX.Element
175171
}

packages/solid-router/tests/Matches.test-d.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from '../src'
1111
import type { AnyRouteMatch, RouteMatch } from '@tanstack/router-core'
1212
import type * as Solid from 'solid-js'
13+
import type { MakeMatchRouteOptions } from '../src'
1314

1415
const rootRoute = createRootRoute()
1516

@@ -234,3 +235,19 @@ test('when filtering useMatches by loaderData with an array', () => {
234235
matches.filter((match) => isMatch(match, 'loaderData.0.comment')),
235236
).toEqualTypeOf<Array<CommentsMatch>>()
236237
})
238+
239+
test('MatchRoute children are typed from resolved params under pathless layouts', () => {
240+
type CommentsMatchRouteChildren = MakeMatchRouteOptions<
241+
DefaultRouter,
242+
string,
243+
'/comments/$id'
244+
>['children']
245+
type CommentsMatchRouteRenderFn = Extract<
246+
CommentsMatchRouteChildren,
247+
(...args: Array<any>) => any
248+
>
249+
250+
expectTypeOf<CommentsMatchRouteRenderFn>().toEqualTypeOf<
251+
(params?: { id: string } | undefined) => Solid.JSX.Element
252+
>()
253+
})

packages/vue-router/src/Matches.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,8 @@ import type {
1515
MakeRouteMatchUnion,
1616
MaskOptions,
1717
MatchRouteOptions,
18-
NoInfer,
1918
RegisteredRouter,
20-
ResolveRelativePath,
2119
ResolveRoute,
22-
RouteByPath,
2320
ToSubOptionsProps,
2421
} from '@tanstack/router-core'
2522

@@ -198,10 +195,7 @@ export type MakeMatchRouteOptions<
198195
// If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns
199196
children?:
200197
| ((
201-
params?: RouteByPath<
202-
TRouter['routeTree'],
203-
ResolveRelativePath<TFrom, NoInfer<TTo>>
204-
>['types']['allParams'],
198+
params?: ResolveRoute<TRouter, TFrom, TTo>['types']['allParams'],
205199
) => Vue.VNode)
206200
| Vue.VNode
207201
}

0 commit comments

Comments
 (0)