Skip to content

Commit 6606802

Browse files
committed
Make missing loaderData conditional in Route.MetaArgs
1 parent 3d76762 commit 6606802

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-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: 98 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,88 @@ 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+
params: unknown;
236+
loaderData: { test: string };
237+
actionData: unknown;
238+
module: { loader: () => { test: string } };
239+
matches: [];
240+
}>["loaderData"],
241+
{ test: string }
242+
>
243+
>,
244+
Expect<
245+
Equal<
246+
CreateMetaArgs<{
247+
params: unknown;
248+
loaderData: { test: string };
249+
actionData: unknown;
250+
module: { loader: () => { test: string }; ErrorBoundary: Func };
251+
matches: [];
252+
}>["loaderData"],
253+
{ test: string } | undefined
254+
>
255+
>,
256+
Expect<
257+
Equal<
258+
CreateMetaArgs<{
259+
params: unknown;
260+
loaderData: never;
261+
actionData: unknown;
262+
module: {};
263+
matches: [];
264+
}>["loaderData"],
265+
never
266+
>
267+
>,
268+
Expect<
269+
Equal<
270+
CreateMetaArgs<{
271+
params: unknown;
272+
loaderData: never;
273+
actionData: unknown;
274+
module: {
275+
ErrorBoundary: Func;
276+
};
277+
matches: [];
278+
}>["loaderData"],
279+
undefined
280+
>
281+
>,
282+
// Test that MetaArgs.data (deprecated) also follows the same pattern
283+
Expect<
284+
Equal<
285+
CreateMetaArgs<{
286+
params: unknown;
287+
loaderData: { test: string };
288+
actionData: unknown;
289+
module: {
290+
loader: () => { test: string };
291+
};
292+
matches: [];
293+
}>["data"],
294+
{ test: string }
295+
>
296+
>,
297+
Expect<
298+
Equal<
299+
CreateMetaArgs<{
300+
params: unknown;
301+
loaderData: { test: string };
302+
actionData: unknown;
303+
module: {
304+
loader: () => { test: string };
305+
ErrorBoundary: Func;
306+
};
307+
matches: [];
308+
}>["data"],
309+
{ test: string } | undefined
310+
>
311+
>,
312+
];

0 commit comments

Comments
 (0)