📐
PrismaでTypeScriptの型を自在に操る!Prisma.validatorの活用
はじめに
Prismaで取得してきたオブジェクトがTypeScriptの型でバリバリコード補完が効いて「すごい!」と思った人は少なくないはずです。
ただし、取得してきたそのオブジェクトの型を他で使おうとしたときに「ん?これどうやって定義したら良いんだ?」と思った人も少なくないはず...。
ということでそんな悩みがある人のためにPrisma.validatorを紹介したいと思います。
前提
まず、以下のようなテーブル構成だったとします。
- UserはProfileと1:1の関係
- UserはPostとは1:多の関係
Prismaのスキーマは以下になります。
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String @db.VarChar(255)
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model Profile {
id Int @id @default(autoincrement())
bio String?
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
articles Post[]
additionalData Profile?
}
課題
例えばユーザーの情報をとってこようと思うと簡単にとってこれるし、コードの補完も効きます。これがPrismaの超便利な機能ですよね。
ただし、とってきたオブジェクトの型をどこか別の場所で使おう(例えば関数のパラメータとして渡したい)とすると、途端に悩ましくなります。
作るのも大変ですし、保守していくのも大変です。
Prisma.validatorを使おう!
そこで使えるのがPrisma.validatorです。
Prisma.validatorで、どのようにDBの情報をとってくるか宣言します。要は find
などをするときに select
や include
に書く中身です。
export const userWithRelations = Prisma.validator<Prisma.UserDefaultArgs>()({
select: {
id: true,
email: true,
name: true,
additionalData: {
select: { bio: true },
},
articles: {
select: { title: true },
},
},
});
この情報をそのまま find
などに渡せますし、
const user = await prisma.user.findFirstOrThrow({
select: userWithRelations.select,
});
以下のように Prisma.XXXGetPayload
を使うことで、
export type UserWithRelations = Prisma.UserGetPayload<typeof userWithRelations>;
find
などを使ったときに取得できるオブジェクトの型も生成できます!
select
や include
を他でも使えるのはもちろんのこと、取得したオブジェクトの形も他で使えるので、とても便利です。
まとめ
- Prismaで取得したオブジェクトの型は自作しない方が良い(保守が大変)
- 取得したオブジェクトの型が明示的に必要な場合はPrisma.validatorを活用する
ということで、少しでもPrismaを快適に使えるようになったらと思います 🚀
Discussion