型安全
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` の間に1対多のリレーションがあります。
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`