Hur man slår in en Prisma-metod och återanvänder typer

Prisma är en lättanvänd ORM med riktigt användbara Typescript-typer som ändrar resultattypen för en fråga baserat på de alternativ du skickar in.

När du bygger ut en applikation kommer du utan tvekan att stöta på en situation där du vill slå in en befintlig Prisma-metod med anpassad logik. Du kan välja att passera igenom typerna så att den som ringer kan bestämma om de vill utöka frågan.

Om du använder Prismas frågeargument förväntar du dig också att få Prismas returtyper.

Detta är inte så lätt som det låter, eftersom att bara skicka data (eller till och med skicka ett generiskt säkerhetskopierat värde) inte fungerar som avsett.

Du kan börja med att prova något sånt här. Slå in uppgiften findMany anrop med en funktion som accepterar Prisma query args, men modifierar frågan för att göra något specifikt.

// DOES NOT WORK
  specialFindMany<T extends Prisma.TodoFindManyArgs>(args?:T){
    return prisma.todo.findMany({
      ...args,
      where:{
        ...args?.where
        isSpecial: true
      }
    })
  }

Detta ger typfel.

Upptäckt

Som med allt annat i Typescript, om du gräver i typerna kan du få fram vad en funktion faktiskt förväntar sig.

Tittar på typerna för todo.findMany() från och med Prisma 2.24.0 du hittar något som ser ut så här:

findMany<T extends TodoFindManyArgs>(
      args?: SelectSubset<T, TodoFindManyArgs>
    ): CheckSelect<T, PrismaPromise<Array<Todo>>, PrismaPromise<Array<TodoGetPayload<T>>>>

Du kan se att de hämtar typen från SelectSubset s generika.

Lösning

Om du kopierar denna typ till både din metods deklaration och prisma.finyMany generisk får du en fungerande maskinskriven passthrough.

   async specialFindMany<T extends Prisma.TodoFindManyArgs>(
    args?: Prisma.SelectSubset<T, Prisma.TodoFindManyArgs>,
  ) ){
    // Other custom logic

    const result = await prisma.todo.findMany<
    Prisma.SelectSubset<T, Prisma.SearchFindManyArgs>>(
      {
      ...args!,
      where:{
        ...args?.where
        isSpecial: true
      }
    })

    // Other custom logic

    return result
  }

Utan att skicka in generiken kommer typerna fortfarande att misslyckas (åtminstone i mina tester).

Eftersom args är valfritt kommer typerna att klaga på att tvinga igenom ett objekt. Det kan finnas en bättre lösning på detta, men jag ! tvingade args-typen att existera.

Slutsats

Det här känns ganska besvärligt, och jag skulle gärna se lite mer flexibelt skrivande i Prisma, men det får jobbet gjort för att slå in databasanrop.

Den här lösningen täcker tyvärr inte utökning av de typer som ingår i Prisma-anropet, så inklusive include eller select kommer inte att resultera i korrekta utdatatyper.

Om du har en bättre lösning, låt mig veta i kommentarerna!!!