跳至主要内容

类型安全

为 Prisma Client 生成的代码包含一些有用的类型和实用程序,您可以使用它们来使您的应用程序更具类型安全性。本页介绍利用它们的模式。

注意:如果您对使用 Prisma ORM 的高级类型安全主题感兴趣,请务必查看这篇关于使用新的 TypeScript satisfies 关键字改进您的 Prisma Client 工作流程的博客文章

导入生成的类型

您可以导入 Prisma 命名空间并使用点表示法访问类型和实用程序。以下示例展示了如何导入 Prisma 命名空间并使用它来访问和使用 Prisma.UserSelect 生成的类型

import { Prisma } from '@prisma/client'

// Build 'select' object
const userEmail: Prisma.UserSelect = {
email: true,
}

// Use select object
const createUser = await prisma.user.create({
data: {
email: '[email protected]',
},
select: userEmail,
})

另请参阅:使用 Prisma.UserCreateInput 生成的类型

什么是生成的类型?

生成的类型是源自您的模型的 TypeScript 类型。您可以使用它们来创建要传递给顶级方法(如 prisma.user.create(...)prisma.user.update(...))或选项(如 selectinclude)的类型化对象。

例如,select 接受一个 UserSelect 类型的对象。它的对象属性与根据模型由 select 语句支持的属性相匹配。

下面的第一个选项卡显示了 UserSelect 生成的类型,以及对象上的每个属性如何具有类型注释。第二个选项卡显示了生成的结果架构模型。

type Prisma.UserSelect = {
id?: boolean | undefined;
email?: boolean | undefined;
name?: boolean | undefined;
posts?: boolean | Prisma.PostFindManyArgs | undefined;
profile?: boolean | Prisma.ProfileArgs | undefined;
}

在 TypeScript 中,类型注释 是当您声明一个变量并添加类型注释来描述变量的类型时。请查看以下示例。

const myAge: number = 37
const myName: string = 'Rich'

这两个变量声明都已添加类型注释,以指定它们是什么原始类型,分别是 numberstring。在大多数情况下,这种注释是不需要的,因为 TypeScript 会根据变量的初始化方式来推断变量的类型。在上面的示例中,myAge 初始化为一个数字,因此 TypeScript 猜测它应该被类型化为数字。

回到 UserSelect 类型,如果您要在创建的对象 userEmail 上使用点表示法,您将可以访问可以使用 select 语句进行交互的 User 模型上的所有字段。

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
profile Profile?
}
import { Prisma } from '@prisma/client'

const userEmail: Prisma.UserSelect = {
email: true,
}

// properties available on the typed object
userEmail.id
userEmail.email
userEmail.name
userEmail.posts
userEmail.profile

同样,您可以使用 include 生成的类型对对象进行类型化,然后您的对象将可以访问可以使用 include 语句的那些属性。

import { Prisma } from '@prisma/client'

const userPosts: Prisma.UserInclude = {
posts: true,
}

// properties available on the typed object
userPosts.posts
userPosts.profile

有关可用不同类型的更多信息,请查看 模型查询选项 参考。

生成的 UncheckedInput 类型

UncheckedInput 类型是一组特殊的生成的类型,允许您执行 Prisma Client 认为“不安全”的操作,例如直接写入 关系标量字段。在执行 createupdateupsert 等操作时,您可以选择“安全”的 Input 类型或“不安全”的 UncheckedInput 类型。

例如,此 Prisma 架构在 UserPost 之间具有一个一对多关系

model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
content String?
author User @relation(fields: [authorId], references: [id])
authorId Int
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}

第一个选项卡显示了 PostUncheckedCreateInput 生成的类型。它包含 authorId 属性,这是一个关系标量字段。第二个选项卡显示了一个使用 PostUncheckedCreateInput 类型的示例查询。如果不存在 id1 的用户,此查询将导致错误。

type PostUncheckedCreateInput = {
id?: number
title: string
content?: string | null
authorId: number
}

可以使用“更安全”的 PostCreateInput 类型重写相同的查询。此类型不包含 authorId 字段,而是包含 author 关系字段。

type PostCreateInput = {
title: string
content?: string | null
author: UserCreateNestedOneWithoutPostsInput
}

type UserCreateNestedOneWithoutPostsInput = {
create?: XOR<
UserCreateWithoutPostsInput,
UserUncheckedCreateWithoutPostsInput
>
connectOrCreate?: UserCreateOrConnectWithoutPostsInput
connect?: UserWhereUniqueInput
}

如果不存在 id1 的作者,此查询也将导致错误。在这种情况下,Prisma Client 将给出更具描述性的错误消息。您还可以使用 connectOrCreate API,如果不存在具有给定 id 的用户,则安全地创建一个新用户。

我们建议尽可能使用“安全”的 Input 类型。

类型实用程序

信息

此功能适用于 Prisma ORM 版本 4.9.0 及更高版本。

为了帮助您创建高度类型安全的应用程序,Prisma Client 提供了一组类型实用程序,这些实用程序可以利用输入和输出类型。这些类型是完全动态的,这意味着它们可以适应任何给定的模型和架构。您可以使用它们来改进项目的自动完成和开发人员体验。

这在 验证输入共享 Prisma Client 扩展 中特别有用。

Prisma Client 中提供以下类型实用程序

  • Exact<Input, Shape>:对 Input 强制执行严格的类型安全性。Exact 确保泛型类型 Input 严格符合您在 Shape 中指定的类型。它 缩小 Input 到最精确的类型。
  • Args<Type, Operation>:检索任何给定模型和操作的输入参数。这对于想要执行以下操作的扩展作者特别有用
    • 重用现有类型来扩展或修改它们。
    • 受益于与现有操作相同的自动完成体验。
  • Result<Type, Arguments, Operation>:获取输入参数并提供给定模型和操作的结果。您通常会在 Args 结合使用它。与 Args 一样,Result 帮助您重用现有类型来扩展或修改它们。
  • Payload<Type, Operation>:检索给定模型和操作的整个结果结构,作为标量和关系对象。例如,您可以使用它在类型级别确定哪些键是标量还是对象。

例如,以下是一种快速方法,您可以通过它强制执行函数的参数与您将传递给 post.create 的参数相匹配

type PostCreateBody = Prisma.Args<typeof prisma.post, 'create'>['data']

const addPost = async (postBody: PostCreateBody) => {
const post = await prisma.post.create({ data: postBody })
return post
}

await addPost(myData)
// ^ guaranteed to match the input of `post.create`