型安全性
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: 'bob@prisma.io',
},
select: userEmail,
})
参照: Prisma.UserCreateInput
生成された型の使用
生成された型とは?
生成された型とは、モデルから派生した TypeScript の型です。これらを使用して、prisma.user.create(...)
や prisma.user.update(...)
などのトップレベルメソッド、または select
や include
などのオプションに渡す型付きオブジェクトを作成できます。
たとえば、select
は UserSelect
型のオブジェクトを受け入れます。そのオブジェクトプロパティは、モデルに従って select
ステートメントでサポートされているものと一致します。
下の最初のタブは UserSelect
生成された型と、オブジェクトの各プロパティがどのように型アノテーションを持つかを示しています。2番目のタブは、型が生成された元のスキーマを示しています。
- 生成された型
- モデル
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
プロパティが含まれています。2番目のタブは、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`