文字列・数値・真偽値のスキーマ — 使える検証メソッド一覧
この章の目次開く
ここからは実際にスキーマを書いていきます。まずはすべての土台になる、単体の値を検証するスキーマからです。
スキーマは「作る」と「検証する」が別々
z.string() を呼んだ時点では、まだ何も検証されません。返ってくるのは検証の設計図であるスキーマオブジェクトで、実際の検証は parse や safeParse を呼んだときに走ります。
const schema = z.string(); // この時点では何も起きない
schema.safeParse('hello'); // ここで初めて検証されるそして、検証メソッドをつなぐと新しいスキーマが返ります。元のスキーマは書き換わりません。
const base = z.string();
const strict = base.min(5);
base.safeParse('ab'); // 成功 — baseは変わっていない
strict.safeParse('ab'); // 失敗 — 5文字以上が必要検証メソッドは元のスキーマを変更せず、条件を足した別のスキーマを返します。だから z.string().min(3).max(10) のようにつなげて書けますし、共通のスキーマを変数に置いて各所で条件を足す、という使い方もできます。
学習者つなげて書けるのは分かったけど、.min() は何を返してるの? 検証結果じゃないの?
先生返ってくるのはスキーマだよ。検証結果が返るのは parse と safeParse だけ。ここを混同すると「.min() の戻り値をifで判定する」みたいなコードを書いてしまうから、最初に押さえておこう。
文字列スキーマ
構文: z.string()
戻り値: 文字列スキーマ。typeof v === 'string' であることを検証する
数値の 123 を渡すと失敗しますが、"123" は文字列なので通ります。空文字も通ることは デフォルト挙動の章のとおりです。
長さ・形を検証するメソッド
| メソッド | 引数 | 何を検証するか |
|---|---|---|
.min(n, message?) | n: 最小文字数 | n 文字以上か |
.max(n, message?) | n: 最大文字数 | n 文字以下か |
.length(n, message?) | n: 文字数 | ちょうど n 文字か |
.regex(re, message?) | re: 正規表現 | パターンに一致するか |
.startsWith(s, message?) | s: 文字列 | s で始まるか |
.endsWith(s, message?) | s: 文字列 | s で終わるか |
.includes(s, message?) | s: 文字列 | s を含むか |
.nonempty(message?) | なし | 1文字以上か(.min(1) と同じ) |
戻り値: いずれも条件を追加した新しいスキーマ。第2引数の message を渡すと、失敗時のメッセージを差し替えられる
const password = z.string().min(8, '8文字以上で入力してください');
password.safeParse('short').error.issues[0].message;
// "8文字以上で入力してください"値を書き換えるメソッド
検証ではなく、値そのものを変換するメソッドもあります。
| メソッド | 効果 |
|---|---|
.trim() | 前後の空白を削除する |
.toLowerCase() | 小文字にする |
.toUpperCase() | 大文字にする |
戻り値: 変換を追加した新しいスキーマ。検証を通ると、変換後の値が data に入る
z.string().trim().parse(' hello '); // "hello"
z.string().toLowerCase().parse('ABC'); // "abc"元の入力ではなく戻り値が変換済みである点に注意してください。この性質は次の章でもう一度扱います。
書く順番で結果が変わる
変換メソッドと検証メソッドは、書いた順に上から実行されます。順番を入れ替えると結果が変わります。
z.string().trim().min(1).safeParse(' ');
// { success: false } — trimして "" になってから長さを見るので弾ける
z.string().min(1).trim().safeParse(' ');
// { success: true, data: "" } — 3文字あるので通過し、そのあとtrimされて空文字になる
文字列フォーマットのスキーマ
メールアドレスやURLのような「形式が決まった文字列」には、専用のスキーマが用意されています。Zod 4ではトップレベルの関数として呼びます。
| スキーマ | 検証する形式 |
|---|---|
z.email() | メールアドレス |
z.url() | URL |
z.uuid() | UUID |
z.iso.date() | 2026-01-01 形式の日付文字列 |
z.iso.datetime() | 2026-01-01T00:00:00Z 形式 |
z.iso.time() | 12:30:00 形式 |
z.ipv4() / z.ipv6() | IPアドレス |
z.jwt() | JWT |
z.base64() | Base64文字列 |
z.nanoid() / z.ulid() / z.cuid2() | 各種ID形式 |
戻り値: 文字列スキーマ。.min() などの文字列メソッドをそのままつなげられる
const schema = z.email().max(255);数値スキーマ
構文: z.number()
戻り値: 数値スキーマ。NaN と Infinity は弾かれる
| メソッド | 引数 | 何を検証するか |
|---|---|---|
.min(n) / .gte(n) | n: 下限 | n 以上か |
.max(n) / .lte(n) | n: 上限 | n 以下か |
.gt(n) / .lt(n) | n: 境界値 | n より大きいか / 小さいか(n 自体は不可) |
.int() | なし | 整数か |
.positive() | なし | 0 より大きいか |
.nonnegative() | なし | 0 以上か |
.negative() / .nonpositive() | なし | 負の数か / 0 以下か |
.multipleOf(n) | n: 倍数の基準 | n の倍数か |
.finite() | なし | 有限の数値か |
戻り値: いずれも条件を追加した新しいスキーマ
境界の扱いは間違えやすいところです。実際の結果で並べます。
| 書き方 | 0 を渡すと |
|---|---|
z.number().positive() | ✗ 失敗 |
z.number().nonnegative() | 通る |
z.number().min(0) | 通る |
その他の基本スキーマ
| スキーマ | 通る値 | 主な用途 |
|---|---|---|
z.boolean() | true / false | フラグ。文字列の "true" は通らない |
z.bigint() | BigInt | 大きな整数 |
z.date() | Date オブジェクト | JSON由来の文字列は通らない |
z.null() | null のみ | union の部品として使う |
z.undefined() | undefined のみ | 同上 |
z.any() | 何でも | 検証を放棄する。型は any |
z.unknown() | 何でも | 検証しないが型は unknown のまま |
z.never() | 何も通らない | 「ここには値が来ないはず」の表明 |
よくあるハマりどころ
.min() の戻り値をifで判定してしまう
.min(3) が返すのはスキーマであって検証結果ではありません。結果がほしいときは parse か safeParse を呼びます。
.trim() を後ろに書いて空文字が通る
前述のとおりです。変換系は検証より先に書きます。
z.boolean() にフォームの値を渡して落ちる
HTMLのフォームやURLクエリから届く値は文字列です。"true" は z.boolean() を通りません。文字列から真偽値に変換したい場合は z.stringbool() を使います。こちらは "false" をちゃんと false に変換してくれます(z.coerce.boolean() は "false" を true にしてしまうので注意してください)。
ちゃんと使うためのポイント
- 検証メソッドは新しいスキーマを返す。元のスキーマは変わらない
-
.trim()などの変換は検証より先に書く。順番で結果が変わる .nonempty()は.min(1)と同じで、空白だけの入力は通る- 数値の
0を許すかどうかで.positive()と.nonnegative()を使い分ける - メールやURLはZod 4ではトップレベルの
z.email()/z.url()
次の章では、作ったスキーマを実際に使う parseとsafeParseの違い を扱います。例外で落とすか、結果を受け取って自分で分岐するか——実務ではほぼ後者を使うことになります。
参考リンク
- Defining schemas - Zod — 全スキーマとメソッドの公式一覧(英語)
- 正規表現 - MDN —
.regex()に渡すパターンの書き方