Skip to content

Commit 180a120

Browse files
authored
typegen: matches and params for child routes (#12397)
1 parent 5ce8667 commit 180a120

File tree

4 files changed

+23
-4
lines changed

4 files changed

+23
-4
lines changed

.changeset/red-eagles-stare.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"@react-router/dev": patch
3+
"react-router": patch
4+
---
5+
6+
Generate wide `matches` and `params` types for child routes
7+
8+
At runtime, `matches` includes child route matches and `params` include child route path parameters.
9+
But previously, we only generated types for parent routes and the current route in `matches` and `params`.
10+
To align our generated types more closely to the runtime behavior, we now generate more permissive, wider types when accessing child route information.

integration/typegen-test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ test.describe("typegen", () => {
5555
import type { Route } from "./+types/product"
5656
5757
export function loader({ params }: Route.LoaderArgs) {
58-
type Test = Expect<Equal<typeof params.id, string>>
58+
type Test1 = Expect<Equal<typeof params.id, string>>
59+
type Test2 = Expect<Equal<typeof params.asdf, string | undefined>>
5960
return { planet: "world" }
6061
}
6162
@@ -287,6 +288,9 @@ test.describe("typegen", () => {
287288
288289
const parent2 = matches[2]
289290
type Test2 = Expect<Equal<typeof parent2.data, { parent2: number }>>
291+
292+
const child1 = matches[4]
293+
type Test3 = Expect<Equal<typeof child1.data, unknown>>
290294
return []
291295
}
292296
@@ -296,6 +300,9 @@ test.describe("typegen", () => {
296300
297301
const parent2 = matches[2]
298302
type Test2 = Expect<Equal<typeof parent2.data, { parent2: number }>>
303+
304+
const child1 = matches[4]
305+
type Test3 = Expect<Equal<typeof child1.data, unknown>>
299306
}
300307
`,
301308
});

packages/react-router-dev/typegen/generate.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ export function generate(ctx: Context, route: RouteManifestEntry): string {
4141
id: "${route.id}"
4242
file: "${route.file}"
4343
path: "${route.path}"
44-
params: {${formatParamProperties(urlpath)}}
44+
params: {${formatParamProperties(
45+
urlpath
46+
)}} & { [key: string]: string | undefined }
4547
module: Module
4648
loaderData: T.CreateLoaderData<Module>
4749
actionData: T.CreateActionData<Module>

packages/react-router/lib/types/route-module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ type MetaMatch<T extends RouteInfo> = Pretty<
4848
type MetaMatches<T extends RouteInfo[]> =
4949
T extends [infer F extends RouteInfo, ...infer R extends RouteInfo[]]
5050
? [MetaMatch<F>, ...MetaMatches<R>]
51-
: [];
51+
: MetaMatch<RouteInfo>[];
5252

5353
export type CreateMetaArgs<T extends RouteInfo> = {
5454
location: Location;
@@ -149,7 +149,7 @@ type Match<T extends RouteInfo> = Pretty<
149149
type Matches<T extends RouteInfo[]> =
150150
T extends [infer F extends RouteInfo, ...infer R extends RouteInfo[]]
151151
? [Match<F>, ...Matches<R>]
152-
: [];
152+
: Match<RouteInfo>[];
153153

154154
export type CreateComponentProps<T extends RouteInfo> = {
155155
params: T["params"];

0 commit comments

Comments
 (0)