Skip to content

Commit 1f06a5e

Browse files
Make missing loaderData conditional in Route.MetaArgs (#14173)
1 parent 3d76762 commit 1f06a5e

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@react-router/dev": patch
3+
---
4+
5+
Update generated `Route.MetaArgs` type so `loaderData` is only potentially undefined when an `ErrorBoundary` export is present

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

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {
1010
ServerDataFunctionArgs,
1111
} from "./route-data";
1212
import type { RouteModule } from "./route-module";
13-
import type { Pretty } from "./utils";
13+
import type { Pretty, Func, Expect, Equal } from "./utils";
1414

1515
type MaybePromise<T> = T | Promise<T>;
1616

@@ -48,6 +48,12 @@ type MetaMatches<T extends Array<MatchInfo>> =
4848
? [MetaMatch<F>, ...MetaMatches<R>]
4949
: Array<MetaMatch<MatchInfo> | undefined>;
5050

51+
type HasErrorBoundary<T extends RouteInfo> = T["module"] extends {
52+
ErrorBoundary: Func;
53+
}
54+
? true
55+
: false;
56+
5157
type CreateMetaArgs<T extends RouteInfo> = {
5258
/** This is the current router `Location` object. This is useful for generating tags for routes at specific paths or query parameters. */
5359
location: Location;
@@ -58,9 +64,13 @@ type CreateMetaArgs<T extends RouteInfo> = {
5864
*
5965
* @deprecated Use `Route.MetaArgs.loaderData` instead
6066
*/
61-
data: T["loaderData"] | undefined;
67+
data:
68+
| T["loaderData"]
69+
| (HasErrorBoundary<T> extends true ? undefined : never);
6270
/** The return value for this route's server loader function */
63-
loaderData: T["loaderData"] | undefined;
71+
loaderData:
72+
| T["loaderData"]
73+
| (HasErrorBoundary<T> extends true ? undefined : never);
6474
/** Thrown errors that trigger error boundaries will be passed to the meta function. This is useful for generating metadata for error pages. */
6575
error?: unknown;
6676
/** An array of the current {@link https://api.reactrouter.com/v7/interfaces/react_router.UIMatch.html route matches}, including parent route matches. */
@@ -215,3 +225,93 @@ export type GetAnnotations<Info extends RouteInfo> = {
215225
// ErrorBoundary
216226
ErrorBoundaryProps: CreateErrorBoundaryProps<Info>;
217227
};
228+
229+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
230+
type __tests = [
231+
// Test that MetaArgs.loaderData is only potentially undefined when ErrorBoundary is present
232+
Expect<
233+
Equal<
234+
CreateMetaArgs<{
235+
module: {
236+
loader: () => { test: string };
237+
};
238+
loaderData: { test: string };
239+
params: unknown;
240+
actionData: unknown;
241+
matches: [];
242+
}>["loaderData"],
243+
{ test: string }
244+
>
245+
>,
246+
Expect<
247+
Equal<
248+
CreateMetaArgs<{
249+
module: {
250+
loader: () => { test: string };
251+
ErrorBoundary: Func;
252+
};
253+
loaderData: { test: string };
254+
params: unknown;
255+
actionData: unknown;
256+
matches: [];
257+
}>["loaderData"],
258+
{ test: string } | undefined
259+
>
260+
>,
261+
Expect<
262+
Equal<
263+
CreateMetaArgs<{
264+
module: {};
265+
loaderData: never;
266+
params: unknown;
267+
actionData: unknown;
268+
matches: [];
269+
}>["loaderData"],
270+
never
271+
>
272+
>,
273+
Expect<
274+
Equal<
275+
CreateMetaArgs<{
276+
module: {
277+
ErrorBoundary: Func;
278+
};
279+
loaderData: never;
280+
params: unknown;
281+
actionData: unknown;
282+
matches: [];
283+
}>["loaderData"],
284+
undefined
285+
>
286+
>,
287+
// Test that MetaArgs.data (deprecated) also follows the same pattern
288+
Expect<
289+
Equal<
290+
CreateMetaArgs<{
291+
module: {
292+
loader: () => { test: string };
293+
};
294+
loaderData: { test: string };
295+
params: unknown;
296+
actionData: unknown;
297+
matches: [];
298+
}>["data"],
299+
{ test: string }
300+
>
301+
>,
302+
Expect<
303+
Equal<
304+
CreateMetaArgs<{
305+
module: {
306+
loader: () => { test: string };
307+
ErrorBoundary: Func;
308+
};
309+
loaderData: { test: string };
310+
params: unknown;
311+
actionData: unknown;
312+
matches: [];
313+
}>["data"],
314+
{ test: string } | undefined
315+
>
316+
>,
317+
];

0 commit comments

Comments
 (0)