Search code examples
typescripttypesprisma

How to get the type of a function on runtime that returns a prisma findFirst operation


I'm trying to create a function like this

export async function retrieveUser(userConditions: Prisma.UserFindFirstArgs) {

    return await prisma.user.findFirst(userConditions)

}

When I execute the function:

const user = await retrieveUser({ include: { bar: true }}) 

my problem is that if I try to type user.bar typescript informs me that 'Property 'bar' does not exist on type...' but if I execute

const user = await prisma.user.findFirst({
    include: { bar: true }
})

then user has a bar property included.

I tried to create a function that retrieves the users with some condition specified on run time but I can't manage to return a type with all the relations, just like prisma.user.findFirst({ include: { bar: true } }) does.

I would like to find a way to make my function retrieveUser to behave just like prisma.user.findFirst does when returning a type.

My function should be able to work with every include/select so I don't want to create a type with Prisma.Validator or such


Solution

  • This is a great question. Would something like this do what you want?

    export async function retrieveUser<T extends Prisma.UserFindFirstArgs>(
      userConditions: T
    ): Promise<Prisma.UserGetPayload<T>> {
      return await prisma.user.findFirst(userConditions);
    }
    

    You could then use this function like this.

    // Example usage with include
    const userWithBar = await retrieveUser({ include: { bar: true } });
    
    // Example usage with select
    const userWithSelectedFields = await retrieveUser({ select: { id: true, name: true } });
    

    In this function, T is a generic type that extends Prisma.UserFindFirstArgs, which means it can accept any valid argument for the findFirst method. risma.UserGetPayload<T> is a utility type from Prisma that will infer the return type based on the include or select options provided.