diff --git a/.changeset/popular-beers-bake.md b/.changeset/popular-beers-bake.md new file mode 100644 index 00000000000..8e3629600fc --- /dev/null +++ b/.changeset/popular-beers-bake.md @@ -0,0 +1,10 @@ +--- +"@remix-run/server-runtime": patch +--- + +Avoid circular references and infinite recursion in types + +"Pretty" or simplified Typescript types are evaluated by eagerly resolving types. +For complex types with circular references, this can cause TS to recurse infinitely. + +To fix this, pretty types are reverted as a built-in DX feature of useLoaderData, useActionData, etc... diff --git a/packages/remix-server-runtime/serialize.ts b/packages/remix-server-runtime/serialize.ts index a7ecbf1e4fb..6fd357b315c 100644 --- a/packages/remix-server-runtime/serialize.ts +++ b/packages/remix-server-runtime/serialize.ts @@ -1,10 +1,6 @@ import type { AppData } from "./data"; import type { TypedDeferredData, TypedResponse } from "./responses"; -// force Typescript to simplify the type -type Pretty = { [K in keyof T]: T[K] } & {}; -type PrettyTransform = [T] extends [U] ? T : Pretty; - type JsonPrimitive = | string | number @@ -29,9 +25,9 @@ type Serialize = T extends NonJsonPrimitive ? never : T extends { toJSON(): infer U } ? U : T extends [] ? [] : - T extends [unknown, ...unknown[]] ? PrettyTransform> : + T extends [unknown, ...unknown[]] ? SerializeTuple : T extends ReadonlyArray ? (U extends NonJsonPrimitive ? null : Serialize)[] : - T extends object ? PrettyTransform>> : + T extends object ? SerializeObject> : never ;