remix-run / remix

Build Better Websites. Create modern, resilient user experiences with web fundamentals.
https://remix.run
MIT License
28.7k stars 2.44k forks source link

useLoaderData loses typings when accessing some data #7821

Open dmarkow opened 9 months ago

dmarkow commented 9 months ago

What version of Remix are you using?

2.1.0

Are all your remix dependencies & dev-dependencies using the same version?

Steps to Reproduce

We use GraphQL's GraphQLError type in some responses. I just updated one of our smaller apps to 2.1.0 and it's now struggling with the return types on these errors. Noticed that Remix now has it's own Jsonify as of 2.1.0 instead of type-fest's.

export const loader = async () => {
  return json({errors: [] as GraphQLError[]})
};

export default function Page() {
  const data = useLoaderData<typeof loader>(); // data is JsonifyObject<{errors: GraphQLError[]; }>

  // But when I try to access `errors`, it loses the type
  const errors = data.errors; // errors is now Unknown[] instead of the expected GraphQLError[]
}

I traced this back to GraphQLError having a toJSON() method. If I remove that, the types are fine. I tried the current version of type-fest for comparison, and it deals with the toJSON method without blowing away the types.

Typescript Playground for some reference

Expected Behavior

Objects returned from actions/loaders that have a toJSON() method preserve their types.

Actual Behavior

Types are lost on objects returned from actions/loaders that have a toJSON() method.

dmarkow commented 9 months ago

I swear I searched first, but just saw #7736 after submitting which hopefully fixes this issue