Skip to content

Commit

Permalink
release: typegen fixes (#12443)
Browse files Browse the repository at this point in the history
* typegen current route info into `matches`

* child matches may be undefined
  • Loading branch information
pcattori authored Dec 2, 2024
1 parent 1007cc7 commit 05d7667
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 8 deletions.
4 changes: 2 additions & 2 deletions .changeset/red-eagles-stare.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"react-router": patch
---

Generate wide `matches` and `params` types for child routes
Generate wide `matches` and `params` types for current route and child routes

At runtime, `matches` includes child route matches and `params` include child route path parameters.
But previously, we only generated types for parent routes and the current route in `matches` and `params`.
But previously, we only generated types for parent routes in `matches`; for `params`, we only considered the parent routes and the current route.
To align our generated types more closely to the runtime behavior, we now generate more permissive, wider types when accessing child route information.
20 changes: 18 additions & 2 deletions integration/typegen-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,25 @@ test.describe("typegen", () => {
import { Expect, Equal } from "../expect-type"
import type { Route } from "./+types/current"
export function loader() {
return { current: 3 }
}
export function meta({ matches }: Route.MetaArgs) {
const parent1 = matches[1]
type Test1 = Expect<Equal<typeof parent1.data, { parent1: number }>>
const parent2 = matches[2]
type Test2 = Expect<Equal<typeof parent2.data, { parent2: number }>>
const current = matches[3]
type Test3 = Expect<Equal<typeof current.data, { current: number }>>
const child1 = matches[4]
type Test3 = Expect<Equal<typeof child1.data, unknown>>
type Test4a = Expect<undefined extends typeof child1 ? true : false>
if (child1) {
type Test4b = Expect<Equal<typeof child1.data, unknown>>
}
return []
}
Expand All @@ -301,8 +311,14 @@ test.describe("typegen", () => {
const parent2 = matches[2]
type Test2 = Expect<Equal<typeof parent2.data, { parent2: number }>>
const current = matches[3]
type Test3 = Expect<Equal<typeof current.data, { current: number }>>
const child1 = matches[4]
type Test3 = Expect<Equal<typeof child1.data, unknown>>
type Test4a = Expect<undefined extends typeof child1 ? true : false>
if (child1) {
type Test4b = Expect<Equal<typeof child1.data, unknown>>
}
}
`,
});
Expand Down
8 changes: 4 additions & 4 deletions packages/react-router/lib/types/route-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ type MetaMatch<T extends RouteInfo> = Pretty<
type MetaMatches<T extends RouteInfo[]> =
T extends [infer F extends RouteInfo, ...infer R extends RouteInfo[]]
? [MetaMatch<F>, ...MetaMatches<R>]
: MetaMatch<RouteInfo>[];
: Array<MetaMatch<RouteInfo> | undefined>;

export type CreateMetaArgs<T extends RouteInfo> = {
location: Location;
params: T["params"];
data: T["loaderData"];
error?: unknown;
matches: MetaMatches<T["parents"]>;
matches: MetaMatches<[...T["parents"], T]>;
};
export type MetaDescriptors = MetaDescriptor[];

Expand Down Expand Up @@ -149,13 +149,13 @@ type Match<T extends RouteInfo> = Pretty<
type Matches<T extends RouteInfo[]> =
T extends [infer F extends RouteInfo, ...infer R extends RouteInfo[]]
? [Match<F>, ...Matches<R>]
: Match<RouteInfo>[];
: Array<Match<RouteInfo> | undefined>;

export type CreateComponentProps<T extends RouteInfo> = {
params: T["params"];
loaderData: T["loaderData"];
actionData?: T["actionData"];
matches: Matches<T["parents"]>;
matches: Matches<[...T["parents"], T]>;
};

export type CreateErrorBoundaryProps<T extends RouteInfo> = {
Expand Down

0 comments on commit 05d7667

Please sign in to comment.