remix: useLoaderData type inference broken when returned data has a `data` key
What version of Remix are you using?
1.11.1
Steps to Reproduce
If the object returned from the loader includes a data key, the type inference returns only the items nested under that key. So in this case, typescript thinks useLoaderData returns just {item: number}. The code works just fine - item and other are being destructured properly and displaying on the page, it’s just the types that are wrong. If I rename the data key to something else, it works fine and typescript returns the full type, e.g. {myData: {item: number}, other: number}. This started when defer was released.
export const loader = async () => {
return json({
data: { item: 1 },
other: 2
})
}
export default function Index() {
const { data: { item }, other } = useLoaderData<typeof loader>();
return <div>Item: {item}, Other: {other}</div>;
}
> yarn tsc
yarn run v1.22.19
$ /Users/dylan/dev/data-issue/node_modules/.bin/tsc
app/routes/index.tsx:12:11 - error TS2339: Property 'data' does not exist on type 'SerializeDeferred<{ item: number; }>'.
12 const { data: { item }, other } = useLoaderData<typeof loader>();
~~~~
app/routes/index.tsx:12:27 - error TS2339: Property 'other' does not exist on type 'SerializeDeferred<{ item: number; }>'.
12 const { data: { item }, other } = useLoaderData<typeof loader>();
~~~~~
Expected Behavior
Type inference should work as it did before, or if data is a reserved name, the documentation should say as much.
Actual Behavior
Typescript infers the wrong types, but the code works fine.
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 28
- Comments: 18 (8 by maintainers)
It looks like it resolved the issue for us from what I can see.
Closed by #5516
Looks like this is the problem. https://github.com/remix-run/remix/blob/006b58bfec02622f9881c1e37444baef60584eda/packages/remix-server-runtime/serialize.ts#L21-L31
https://github.com/remix-run/remix/blob/006b58bfec02622f9881c1e37444baef60584eda/packages/remix-server-runtime/responses.ts#L9-L14
TypedDeferredData<infer U>matches on our result because there is a data key, instead of moving down toSerializeObjectwhich it should since I’m not actually usingdefer.1.16.0 is out 🎉
This is still an issue with actions, typed loaders are working for me.
Meaning,
useActionData<typeof action>()is inferred completely wrong.I’ve this problem as well with the latest version of Remix. I just wanted to add that it also happens when using useFetcher in actions.
Reproduced this in a minimal repository for you: https://github.com/emilbryggare/remix-types/
This still occurs on Remix 1.15, and it also occurs on the
SerializeFromtype helper, and theuseFetcher<Type>()generic type.I also have a typescript playground for testing.