在 prisma 客户端上获取完整类型

duf*_*aux 36 prisma

当我使用 prismagenerate 生成 prisma 客户端时,我得到了一个包含数据库中所有类型的 index.d.ts 。但问题是所有类型都是“单一”的并且没有任何关系。当我查询类似的东西时

prisma.users.findMany({
            [... ]
            include: {
                cars: {
                  [...]
                }}});
Run Code Online (Sandbox Code Playgroud)

prisma 使用正确的类型动态输入响应

users & {
        cars: cars & {
           [...]
        };
    }
Run Code Online (Sandbox Code Playgroud)

所以一切正常,我有自动完成功能,除非我想将此变量传递给另一个方法,我想输入参数,所以我必须创建自己的类型用作方法参数。

type prismaUsers = users & {
        cars?: cars & {
           [...]
        };
    }
Run Code Online (Sandbox Code Playgroud)

但我问是否有一种方法可以从 prisma 获取“完整”类型,以避免我像在用户示例中那样创建带有可选子元素的所有“完整”类型。或者也许我做错了,还有其他方法可以做?

joe*_*une 60

获取“完整”类型或具有所有可能关系的模型的另一种方法(我的偏好)是使用GetPayload模型类型的版本。该类型是一个泛型,可以接收传递给查询的相同对象。

import { PrismaClient, Prisma } from "@prisma/client";

const prisma = new PrismaClient();

type UserWithCars = Prisma.UserGetPayload<{
  include: {
    cars: true;
  }
}>

const usersWithCars = await prisma.user.findMany({
  include: {
    cars: true,
  }
});
Run Code Online (Sandbox Code Playgroud)

随着您的查询变得越来越复杂,您可能需要对其进行抽象并确保它是强类型的。

import { Prisma, PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

const userInclude = Prisma.validator<Prisma.UserInclude>()({
  cars: true,
});

type UserWithCars = Prisma.UserGetPayload<{
  include: typeof userInclude;
}>;

const usersWithCars = await prisma.user.findMany({
  include: userInclude,
});

Run Code Online (Sandbox Code Playgroud)

  • 投票因为您的解决方案不需要创建一个函数来检索类型:) 谢谢! (4认同)

Tas*_*mam 15

您可以使用Prisma Validator API以及一些 TypeScript 功能来生成查询的类型。

对于findMany你提到的例子

import { Prisma } from '@prisma/client'

// 1. Define a User type that includes the "cars" relation. 
const userWithCars = Prisma.validator<Prisma.UserArgs>()({
    include: { cars: true },
})

// 2: This type will include many users and all their cars
type UserWithCars = Prisma.UserGetPayload<typeof userWithCars>[]

Run Code Online (Sandbox Code Playgroud)

如果您只是想自动推断函数中包装的 prisma 查询的返回类型,您可以使用PromiseReturnType.

例如:

import { Prisma } from '@prisma/client'

async function getUsersWithCars() {
  const users = await prisma.user.findMany({ include: { cars: true } });
  return users;
}

type UsersWithCars = Prisma.PromiseReturnType<typeof getUsersWithCars>

Run Code Online (Sandbox Code Playgroud)

您可以在 Prisma 文档中的针对模型类型的部分结构进行操作概念指南中阅读有关此内容的更多信息。


Cam*_*CHN 8

最好的方法是使用像这样的通用类型:

import { Prisma } from '@prisma/client'

type UserWithMessages = Prisma.UserGetPayload<{
  include: {
    Message: {
      include: {
        MessageParam: true;
      };
    };
  };
}>;
Run Code Online (Sandbox Code Playgroud)


sht*_*se8 8

具有所有关系的完整模型类型。

type UserFullType = Prisma.UserGetPayload<{ select: { [K in keyof Required<Prisma.UserSelect>]: true } }>
Run Code Online (Sandbox Code Playgroud)

为了方便起见,您还可以创建地图。

interface SelectMap {
  User: Prisma.UserSelect
  Post: Prisma.PostSelect
}

interface PayloadMap<S extends (string | number | symbol)> {
  User: Prisma.UserGetPayload<{ [K in S]: true }>
  Post: Prisma.PostGetPayload<{ [K in S]: true }>
}

type FullModel<M extends keyof SelectMap, S = Required<SelectMap[M]>> = PayloadMap<keyof S>[M]
Run Code Online (Sandbox Code Playgroud)

用法

const user: FullModel<'User'>
Run Code Online (Sandbox Code Playgroud)

更新

这是使用模型类型作为泛型的解决方案

type ValueOf<T> = T[keyof T]
type PickByValue<T, V extends T[keyof T]> = { [ K in Exclude<keyof T, ValueOf<{ [ P in keyof T ]: T[P] extends V ? never : P }>> ]: T[K] }
type KeyOfValue<T, V extends T[keyof T]> = keyof PickByValue<T, V>
type PickValueByKey<T, K> = K extends keyof T ? T[K] : never

interface ModelMap {
  Article: Article
  User: User
}
interface SelectMap {
  Article: Prisma.ArticleSelect
  User: Prisma.UserSelect
}
interface PayloadMap<S extends (string | number | symbol)> {
  Article: Prisma.ArticleGetPayload<{ select: { [K in S]: true } }>
  User: Prisma.UserGetPayload<{ select: { [K in S]: true } }>
}
type FullModelType<M extends ValueOf<ModelMap>, N = KeyOfValue<ModelMap, M>, S = Required<PickValueByKey<SelectMap, N>>> = PickValueByKey<PayloadMap<keyof S>, N>
const article: FullModelType<Article> = {}
Run Code Online (Sandbox Code Playgroud)


day*_*ily 1

您可以最轻松地使用以下命令定义相应的类型typeof

myQuery = await prisma.users.findMany({
            [... ]
            include: {
                cars: {
                  [...]
                }}});
type prismaUsers = typeof myQuery
Run Code Online (Sandbox Code Playgroud)

或者,如果您决定将查询包装在函数中,您可以让 TypeScript 为您推断返回类型:

function queryUserWithCar(...) {
  return prisma.users.findMany({
            [... ]
            include: {
                cars: {
                  [...]
                }}});
}
Run Code Online (Sandbox Code Playgroud)

然后提取函数的返回类型:

type prismaUser = ReturnType<typeof queryUserWithCar> extends Promise<infer T> ? T : never
Run Code Online (Sandbox Code Playgroud)