From c9487e672f463f0e58a1dae900e21c124b0ec5f3 Mon Sep 17 00:00:00 2001 From: Pedro Cattori Date: Wed, 11 Dec 2024 17:17:37 -0500 Subject: [PATCH] ignore redirects when inferring loader data types (#12527) --- .changeset/khaki-gifts-grin.md | 5 +++++ packages/react-router/lib/router/utils.ts | 9 +++++++-- packages/react-router/lib/types/route-data.ts | 8 ++++++-- 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 .changeset/khaki-gifts-grin.md diff --git a/.changeset/khaki-gifts-grin.md b/.changeset/khaki-gifts-grin.md new file mode 100644 index 0000000000..c19f1feb79 --- /dev/null +++ b/.changeset/khaki-gifts-grin.md @@ -0,0 +1,5 @@ +--- +"react-router": patch +--- + +Ignore redirects when inferring loader data types diff --git a/packages/react-router/lib/router/utils.ts b/packages/react-router/lib/router/utils.ts index 8042099e5e..c80dab7ccb 100644 --- a/packages/react-router/lib/router/utils.ts +++ b/packages/react-router/lib/router/utils.ts @@ -1367,7 +1367,12 @@ export interface TrackedPromise extends Promise { export type RedirectFunction = ( url: string, init?: number | ResponseInit -) => Response; +) => Redirect; + +// use a `unique symbol` to create a branded type +// https://egghead.io/blog/using-branded-types-in-typescript +declare const redirectSymbol: unique symbol; +export type Redirect = Response & { [redirectSymbol]: never }; /** * A redirect response. Sets the status code and the `Location` header. @@ -1389,7 +1394,7 @@ export const redirect: RedirectFunction = (url, init = 302) => { return new Response(null, { ...responseInit, headers, - }); + }) as Redirect; }; /** diff --git a/packages/react-router/lib/types/route-data.ts b/packages/react-router/lib/types/route-data.ts index 5da38cf3e1..f2d8c41ff7 100644 --- a/packages/react-router/lib/types/route-data.ts +++ b/packages/react-router/lib/types/route-data.ts @@ -2,7 +2,7 @@ import type { ClientLoaderFunctionArgs, ClientActionFunctionArgs, } from "../dom/ssr/routeModules"; -import type { DataWithResponseInit } from "../router/utils"; +import type { DataWithResponseInit, Redirect } from "../router/utils"; import type { Serializable } from "../server-runtime/single-fetch"; import type { Equal, Expect, Func, IsAny, Pretty } from "./utils"; @@ -44,11 +44,13 @@ type DataFrom = // prettier-ignore type ClientData = + T extends Redirect ? never : T extends DataWithResponseInit ? U : T // prettier-ignore type ServerData = + T extends Redirect ? never : T extends DataWithResponseInit ? Serialize : Serialize @@ -84,6 +86,7 @@ type __tests = [ | { data: string; b: Date; c: undefined } > >, + Expect { a: string } | Redirect>, { a: string }>>, // ClientDataFrom Expect, undefined>>, @@ -105,5 +108,6 @@ type __tests = [ | { json: string; b: Date; c: () => boolean } | { data: string; b: Date; c: () => boolean } > - > + >, + Expect { a: string } | Redirect>, { a: string }>> ];