でじぼうです。
Zodを使ったバリデーションで一番よく出てくるのが .object()
でも実際の現場では、それだけでは足りないことが多いです。
この記事では .object()
と一緒によく使う構文だけにしぼって、未経験でもわかるように解説します!

この記事は下記の方がおすすめ!
- Zodってなに?
- .object() ってなに?
- よく使われる構文の違いが知りたい
Instagramフォロワー数9,500人を越える人気のもち・大福店 えにかいたもち
Zodとは?
Zodは、TypeScriptで「入力ルール(バリデーション)」を簡単に定義できるライブラリです。
- 形式チェック(文字列・数値・メールなど)
- 必須・任意の設定
- 条件付きのチェック
などが、読みやすい構文で書けるのが特徴です。
より詳細は下記のブログをご確認ください。
.object()とは?
フォーム全体の「入力ルール」をまとめて定義できる、Zodの土台です。
const schema = z.object({
name: z.string(),
email: z.string().email(),
});
コードの意味
name
は文字列の入力が必要(必須)email
はメール形式での入力が必要(必須)
このように、.object()
を使うことで複数の入力項目を1つのスキーマとしてまとめることができます。
一緒によく使う構文一覧【目的別】
構文 | できること | 使用頻度 |
---|---|---|
.superRefine() | 複数項目をまとめてチェック | ◎ よく使う |
.partial() (パーシャル) | 全ての項目を「入力なしでもOK」に | ◎ よく使う |
.merge() | スキーマ同士を合体 | ○ 時々使う |
.extend() | 既存のスキーマに追加する | ○ 時々使う |
.pick() | 一部の項目だけ取り出す | ○ 時々使う |
.omit() | 一部の項目を除外する | ○ 時々使う |
.superRefine()とは?
複数項目を「まとめてチェック」したいときに利用します。
const schema = z.object({
password: z.string(),
confirm: z.string(),
}).superRefine((data, ctx) => {
if (data.password !== data.confirm) {
ctx.addIssue({
path: ["confirm"],
message: "パスワードが一致しません",
code: z.ZodIssueCode.custom,
});
}
});
コードの意味
📘 data
とは?
z.object({...})
に渡したすべての入力値(name, email など)が入っているオブジェクトのことを指す- React Hook Form の
getValues()
と同じ構造
📘 ctx.addIssue()
とは?
- 条件に合致した場合に、「この項目にエラーがある」と Zod に伝える関数
path: ["confirm"]
と指定すれば、confirm
にエラーメッセージが表示できるcode: z.ZodIssueCode.custom
は「独自ルールによるエラー」であることを示す
📘コード全体の意味
.superRefine()
は、バリデーションの対象全体(objectの中身)にアクセスできる関数password
とconfirm
が一致していなければ、confirm
項目にエラーを追加
よくある使い方
- パスワード確認
- 日付の前後関係
- 条件付き入力のバリデーション
.partial()とは?
全部「任意入力」にするときに利用します。
const schema = z.object({
title: z.string(),
content: z.string(),
}).partial();
コードの意味
title
もcontent
も、未入力でもエラーにならない
よくある使い方
- 入力フォームで、どれか1つだけ更新したいとき(プロフィール編集など)
- 一部だけ更新するような画面で、全項目が必須でないとき
.optional() でも同じ意味になる
下記の記載は、上記の
で定義した場合と、結果はまったく同じになります。.partial()
const schema = z.object({
title: z.string().optional(),
content: z.string().optional(),
});
では .partial() を使うメリットは?
- プロパティがたくさんあるときに 1つずつ
.optional()
を書かなくて済む - スキーマを再利用する際に、必須版と任意版を簡単に切り替えられる
✅ .optional()
を個別に書いてもOK
✅ .partial()
は 全部を一括で optional にしたいときに便利!
.merge()とは?
共通ルールと追加ルールを「合体する」ときに利用します。
const base = z.object({ id: z.string() });
const detail = z.object({ name: z.string() });
const schema = base.merge(detail);
コードの意味
id
とname
の両方を含んだ1つのスキーマを作る
よくある使い方
- IDだけで定義した共通スキーマに、画面ごとの入力項目(詳細)を足したいとき
- 共通部分と画面ごとの違いを分けて管理したいとき(保守性アップ)
.extend()とは?
既存のスキーマに追加するときに利用します。
const user = z.object({ name: z.string() });
const extended = user.extend({ age: z.number() });
コードの意味
user
にage
を追加した新しいスキーマを作る
よくある使い方
- もとのスキーマを壊さずに追加したいとき(再利用性アップ)
- 複数画面で
user
は共通だが、年齢が必要なのは一部だけ…という場面など
.pick()とは?
必要な項目だけ「取り出す」ときに利用します。
const full = z.object({
name: z.string(),
email: z.string(),
age: z.number(),
});
const nameOnly = full.pick({ name: true });
コードの意味
name
だけを含むスキーマを作る
よくある使い方
- 一覧画面などで、一部の情報だけ使いたいとき
- 画面に表示するフィールドを限定したいとき
.omit()とは?
不要な項目だけ「除外する」ときに利用します。
const full = z.object({
name: z.string(),
email: z.string(),
age: z.number(),
});
const noEmail = full.omit({ email: true });
コードの意味
email
を除外したスキーマを作る
よくある使い方
- セキュリティ上、特定の項目を外したいとき(たとえばパスワードなど)
- APIレスポンスで不要な情報を含めたくないとき
補足:.refine() は .object() の中で「項目ごと」に使う
.refine()
は単体の項目に対して使い、複数項目にまたがるときは .superRefine()
を使います。
z.object({
username: z.string().refine(val => val !== "admin", {
message: "admin は使えません",
}),
});
コードの意味
username
が “admin” だったらエラーになる、という1つの項目に対する条件
コメント