类型安全
为 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(...)
)或选项(如 select
或 include
)的类型化对象。
例如,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;
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
profile Profile?
}
在 TypeScript 中,类型注释 是当您声明一个变量并添加类型注释来描述变量的类型时。请查看以下示例。
const myAge: number = 37
const myName: string = 'Rich'
这两个变量声明都已添加类型注释,以指定它们是什么原始类型,分别是 number
和 string
。在大多数情况下,这种注释是不需要的,因为 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 认为“不安全”的操作,例如直接写入 关系标量字段。在执行 create
、update
或 upsert
等操作时,您可以选择“安全”的 Input
类型或“不安全”的 UncheckedInput
类型。
例如,此 Prisma 架构在 User
和 Post
之间具有一个一对多关系
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
类型的示例查询。如果不存在 id
为 1
的用户,此查询将导致错误。
- 生成的类型
- 示例查询
type PostUncheckedCreateInput = {
id?: number
title: string
content?: string | null
authorId: number
}
prisma.post.create({
data: {
title: 'First post',
content: 'Welcome to the first post in my blog...',
authorId: 1,
},
})
可以使用“更安全”的 PostCreateInput
类型重写相同的查询。此类型不包含 authorId
字段,而是包含 author
关系字段。
- 生成的类型
- 示例查询
type PostCreateInput = {
title: string
content?: string | null
author: UserCreateNestedOneWithoutPostsInput
}
type UserCreateNestedOneWithoutPostsInput = {
create?: XOR<
UserCreateWithoutPostsInput,
UserUncheckedCreateWithoutPostsInput
>
connectOrCreate?: UserCreateOrConnectWithoutPostsInput
connect?: UserWhereUniqueInput
}
prisma.post.create({
data: {
title: 'First post',
content: 'Welcome to the first post in my blog...',
author: {
connect: {
id: 1,
},
},
},
})
如果不存在 id
为 1
的作者,此查询也将导致错误。在这种情况下,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`