跳到主要内容

类型安全

为 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 上使用点表示法,你将可以访问 User 模型上的所有字段,这些字段可以使用 select 语句进行交互。

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`