#Typescript Loader Type

1 messages · Page 1 of 1 (latest)

unreal wadi
#

So I have created a component that takes in an object from my database. I'm using prisma.

In my component I'm using the type from Prisma but the type on the page is "serialized" due to it coming from a loader. How can I set up the type of the object int he component to match what is coming from the loader. I see the SerializeFrom but that's not exactly what I"m looking for. Any ideas?

grim palm
#

does typeof loader work?

steady kite
#

@grim palm I think I do what you are saying. @unreal wadi My code looks like this:

#

As long as I use LoaderFunction and typeof loader TypeScript seems to understand that the result of useLoaderData will be SerializeFrom<prisma-result> when getPostByUuid() returns prisma-result from prisma.

unreal wadi
#

Yeah sorry I should be a bit more clear. This is a component that is separate from the route. Usually j would use typeof loader but I want this component to work on a bunch of routes so it needs to have a prop interface that matches the types of the loader data. I need to use some sort of serialize type helper but I’m not sure this is exported.

blazing crown
# unreal wadi Yeah sorry I should be a bit more clear. This is a component that is separate fr...

Oh boy... I got really interested into this question, tried getting something together for it cause i though "this shouldn't be too bad". I was really wrong... Tried many different type definitions and return type methods, all of them were giving me some pretty nasty typescript errors that were not very helpful in getting progress. My first attempt was trying to add a return type to the loader where it extended the interface needed for the component, but that gave the following error:

'BaseOption' is assignable to the constraint of type 'S', but 'S' could be instantiated with a different subtype of constraint 'BaseOption'
#

I don't know of a great way to do that sadly, I've tried some other things like making a useLoaderData wrapper that enforces types but that doesn't seem to answer the direct question because you still have to feed in the typeof loader into it, it'll just error when the loader doesnt return the type you need.

#

It seems like you have to enforce the return type of the loader, but doing so does not seem to have a straightforward answer

#

Example of that:

export const loader = async ({
    request,
}: LoaderArgs) : Promise<TypedResponse<SatisfiesLoader>> => {
    return json({hello: "World"});
};

But you can't easily make an interface or something that extends that, doing so causes the above error I mentioned

#
// this results in the above Error
export const loader = async <T extends SatisfiesLoader>({
    request,
}: LoaderArgs) : Promise<TypedResponse<T>> => {
    return json({hello: "World"});
};
#

The only suggestion I can make that would make this process 100 times easier and actually possible, is consider looking into Full Stack Components and see if that will satisfy what you're looking to do

#

The answer could be rather than forcing loaders to return a certain something, have the component itself fetch the certain something and that'll greatly simplify the type logic

unreal wadi
#

Yeah I've used full stack components a few times but that doesn't work well for this use case. I think Remix just needs to export the right type helper. Serialized has to use it under the hoood

blazing crown
#

Well if you want to always manually type your loaders to make them work you definitely can, just the generic method doesnt work. But if you instead did:

  export interface ThisLoader extends SatisfiesLoader{
    your_extra_fields: string;
  }
  export const loader = async ({
    request,
}: LoaderArgs) : Promise<TypedResponse<ThisLoader>> => {
    return json({hello: "World", your_extra_fields: "can go here"});
};
blazing crown
#

it just borks a lot of type inference

#

and that's a rough way to work in Typescript

thorny flint
#
import type { LoaderArg } from “@remix-run/dev”;
export function loader({}: LoaderArg) {}

// in the component
useLoaderData<typeof loader>()
unreal wadi
#

@thorny flint That's what I usually do but in this case I have a component that is used across multiple routes and takes the data from the loader as the prop. The issue is that the data has a "date" on it which makes the types not match.

thorny flint