zod-prisma-typesを活用して型安全なアプリケーションを構築する
はじめまして、ikechan こといけがわです。
今回は業務でtypescriptを使用したプロジェクトで活用しているzod-prisma-types
の基本的な使い方から設定オプションについて順に解説していきます。
目次
- 概要
- インストール
- Prisma Schemaの設計
- バリデーションルール
- generator zodオプションの紹介
- 実際の使用例
- まとめ
1. 概要
zod-prisma-types
はPrismaスキーマからZodバリデーションスキーマを自動生成し、型安全な開発を助けるライブラリです。
2. インストール
npm install zod-prisma-types
# または
yarn add zod-prisma-types
# または
pnpm add zod-prisma-types
3. Prisma Schemaの設計
generator zod {
provider = "zod-prisma-types"
output = "./generated/zod" // 出力ディレクトリの指定
useMultipleFiles = true // スキーマを複数ファイルに分割
writeBarrelFiles = false // バレルファイルの生成を無効化
createInputTypes = false // 入力タイプの生成を無効化
createModelTypes = true // モデルタイプの生成を有効化
addInputTypeValidation = true // 入力タイプに対するバリデーションの追加
createOptionalDefaultValuesTypes = true // デフォルト値を持つフィールドをオプショナルに
createRelationValuesTypes = true // リレーションフィールドを含むタイプの生成
createPartialTypes = true // 全フィールドをオプショナルにしたパーシャルタイプの生成
useDefaultValidators = false // Zodのデフォルトバリデータの使用を無効化
}
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
/// @zod.string.max(30, { message: "Please enter less than 30 characters" })
name String
/// @zod.string.email().max(255, { message: "255字未満で入力してください" })
email String
password String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
address Address?
}
model Address {
id String @id @default(uuid())
userId String @unique
name String
kana String
phone String
country Country
prefecture String
cityAndStreet String
building String
postalCode String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id])
}
enum Country {
jp
us
cn
it
ch
}
5. generator zodオプションの詳細
- *
zod-prisma-types
*の設定オプションを活用することで、生成されるスキーマのカスタマイズが可能です。以下に、主なオプションとその使用方法を示します。
generator zod {
provider = "zod-prisma-types"
output = "./generated/zod" // default is ./generated/zod
useMultipleFiles = false // default is false
writeBarrelFiles = true // default is true
createInputTypes = false // default is true
createModelTypes = true // default is true
addInputTypeValidation = true // default is true
addIncludeType = true // default is true
addSelectType = true // default is true
validateWhereUniqueInput = true // default is true
createOptionalDefaultValuesTypes = false // default is false
createRelationValuesTypes = false // default is false
createPartialTypes = false // default is false
useDefaultValidators = true // default is true
coerceDate = true // default is true
writeNullishInModelTypes = false // default is false
prismaClientPath = "./path/to/prisma/client" // default is client output path
}
-
provider
使用するジェネレーターを指定します。"zod-prisma-types"が標準の設定値です。 -
output
生成されるZodスキーマファイルが保存されるディレクトリのパス。
例: "./generated/zod"。 -
useMultipleFiles
trueに設定すると、各Prismaモデルに対応するZodスキーマが個別のファイルとして生成されます。 -
writeBarrelFiles
falseに設定すると、各ディレクトリのバレルファイル(一括エクスポート用のインデックスファイル)の生成がスキップされます。 -
createInputTypes
falseに設定すると、Prismaの入力タイプに相当するZodスキーマの生成が行われません。 -
createModelTypes
trueに設定すると、Prismaモデルに基づいたZodスキーマの生成が行われます。 -
addInputTypeValidation
trueに設定すると、入力タイプスキーマにカスタムバリデーションルールが追加されます。 -
createOptionalDefaultValuesTypes
trueに設定すると、デフォルト値を持つフィールドがオプショナルとして扱われるZodスキーマが生成されます。 -
createRelationValuesTypes
trueに設定すると、リレーションを持つモデルのためのZodスキーマが生成され、リレーションフィールドを含むタイプが追加されます。 -
createPartialTypes
trueに設定すると、モデルの全フィールドをオプショナルにした「パーシャル」タイプのZodスキーマが生成されます。 -
useDefaultValidators
falseに設定すると、Zodによるデフォルトのバリデーション(例: 文字列長のチェック)が適用されなくなります。
6. バリデーションルールの強化
オプションが沢山ありますが、ここではcreateModelTypes
にフォーカスを当てて説明したいと思います。createModelTypes
はデフォルトでtrue
で設定されている為、特に指定しなくても使用できます。
以下の様にPrismaモデルにコメントを追加することで、Zodバリデーションルールを簡単に追加できます。
model User {
id String @id @default(uuid())
/// @zod.string.max(30, { message: "Please enter less than 30 characters" })
name String
/// @zod.string.email().max(255, { message: "255字未満で入力してください" })
}
エラーメッセージに設定する言語は英語だけでなく日本語も対応しています。
export const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().max(30, { message: "Please enter less than 30 characters" }),
email: z.string().email().max(255, { message: "255字未満で入力してください" }),
password: z.string(),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
})
7. 実際の簡単な使用例
豊富なオプションがありますが、最近のプロジェクトでは最低限のファイルを生成するようにcreateInputTypes = false
としています。
generator zod {
provider = "zod-prisma-types"
createInputTypes = false
}
APIリクエストをバリデートする際に、生成されたZodスキーマUserSchema
を以下のように使用します。
import { Hono } from 'hono';
import { PrismaClient } from '@prisma/client';
import { UserSchema, AddressSchema } from './generated/zod';
const app = new Hono();
const prisma = new PrismaClient();
// ユーザー登録エンドポイント
app.post('/register/user', async (c) => {
try {
// リクエストボディのバリデーション
const userData = UserSchema.parse(c.req.body);
// バリデーションが成功したら、Prismaクライアントを使ってデータベースにユーザーを登録
const user = await prisma.user.create({
data: userData,
});
return c.json(user, 201);
} catch (error) {
// バリデーションエラーの場合
return c.json({ message: error.message }, 400);
}
});
8. まとめ
今回はtypescriptを利用しているプロジェクトでzod-prisma-types
を利用する方法について紹介しました。
現在のプロジェクトではオプションの多くを活用していない状況ですが、徐々に上手く活用できるようにしていきたいです!
型安全性を高めながら開発プロセスの生産性を向上させるための強力なツールですので、ご興味持たれた方は一度利用してみてください!
最後に、toraco株式会社ではエンジニアを積極採用中です。
フロントエンドエンジニア、バックエンドエンジニア、クラウドインフラエンジニアなど職種問わず、様々な技術領域にチャレンジできます。また、PM(プロジェクトマネージャー) や EM(エンジニアリングマネージャー)のキャリアパスも用意しています。
興味のある方は Wantedly,typeの募集をぜひ読んでください!
お知らせ
最後に、toraco株式会社では2024年11月1日にエンジニア向けのコミュニティを立ち上げました。
Discord のサーバーで運営しており、以下のリンクから無料で参加できます。コミュニティ内では以下のような投稿・活動がされます!
Discussion