2. オブジェクト・コレクション・Union・ラッパーコンビネータ
本モジュールでは、Zod v4.6.7 の複合コンテナスキーマ (ZodObject, ZodArray, ZodTuple, ZodRecord, ZodMap, ZodSet)、代数的 Union / Intersection コンビネータ (ZodUnion, ZodXor, ZodDiscriminatedUnion, ZodIntersection)、ラッパー修飾子 (ZodOptional, ZodExactOptional, ZodNullable, ZodDefault, ZodPrefault, ZodNonOptional, ZodCatch, ZodReadonly, $ZodBranded)、再帰・カスタムスキーマ (z.lazy, z.custom, z.instanceof, z.json)、およびランタイム関数・Promise ラッパー (ZodFunction, ZodPromise) を定義します。
Source Code
from drawlib import canvas
from drawlib.diagrams.architecture import ArchitectureDiagram, Node, NodeGroup, PhosphorIcon
from drawlib.lines import line
from drawlib.styles import Styles
from drawlib.text import text
canvas.clear()
canvas.setup(width=184, height=106, dpi=150)
text(
(92, 100.5),
"Zod v4.6.7 複合スキーマ階層 (オブジェクト・コレクション・Union)",
style=Styles.DarkBold.patch(text_size=13.0),
)
d = ArchitectureDiagram(
node_style=Styles.PrimaryBold,
node_text_style=Styles.DarkBold.patch(text_size=10.0),
edge_style=Styles.PrimaryBold,
edge_text_style=Styles.DarkBold.patch(text_size=10.0),
node_card_style=Styles.Neutral,
)
# Root Base Class
root = d.add(
Node(
"ZodType<Output, Input> (コンテナ基底 + メモ化 Shape 解決)\nparse / safeParse / check / toJSONSchema / ~standard",
width=102,
height=12.5,
icon=PhosphorIcon.CUBE,
icon_size=5.8,
style=Styles.WhiteBold,
text_style=Styles.WhiteBold.patch(text_size=10.5),
card_style=Styles.PrimaryFlat,
),
xy=(88.0, 84.0),
)
# Group 1: Object Schemas
g_obj = d.add(
NodeGroup(title="オブジェクト ($ZodObjectJIT)", padding=4.5),
xy=(2.0, 4.0),
)
g_obj.add(
Node("ZodObject ($strip)\nz.object(shape)", width=46, height=12.5, icon=PhosphorIcon.BRACKETS_CURLY, icon_size=5.5, style=Styles.WhiteBold, text_style=Styles.WhiteBold.patch(text_size=10.0), card_style=Styles.AccentFlat),
xy=(27.5, 49.0),
)
g_obj.add(
Node("z.strictObject(shape)\ncatchall: z.never()", width=46, height=12.5, icon=PhosphorIcon.LOCK_KEY, icon_size=5.5, card_style=Styles.PrimaryNeutral),
xy=(27.5, 34.0),
)
g_obj.add(
Node("z.looseObject(shape)\ncatchall: z.unknown()", width=46, height=12.5, icon=PhosphorIcon.ARROWS_OUT_SIMPLE, icon_size=5.5, card_style=Styles.Neutral),
xy=(27.5, 19.0),
)
g_obj.add(
Node("Shape コンビネータ\nextend / pick / omit / partial", width=46, height=12.5, icon=PhosphorIcon.SLIDERS, icon_size=5.5, card_style=Styles.Neutral),
xy=(27.5, 4.0),
)
# Group 2: Collection Schemas
g_col = d.add(
NodeGroup(title="コレクション & Key-Value スキーマ", padding=4.5),
xy=(61.0, 4.0),
)
g_col.add(
Node("ZodArray<T>\nz.array(el) / min / max", width=48, height=12.5, icon=PhosphorIcon.BRACKETS_SQUARE, icon_size=5.5, card_style=Styles.PrimaryNeutral),
xy=(28.5, 49.0),
)
g_col.add(
Node("ZodTuple<T, Rest>\nz.tuple([...], rest?)", width=48, height=12.5, icon=PhosphorIcon.LIST_NUMBERS, icon_size=5.5, card_style=Styles.Neutral),
xy=(28.5, 34.0),
)
g_col.add(
Node("ZodRecord<K, V>\nrecord / partial / loose", width=48, height=12.5, icon=PhosphorIcon.TABLE, icon_size=5.5, card_style=Styles.Neutral),
xy=(28.5, 19.0),
)
g_col.add(
Node("ZodMap & ZodSet\nz.map(k, v) / z.set(v)", width=48, height=12.5, icon=PhosphorIcon.STACK, icon_size=5.5, card_style=Styles.Neutral),
xy=(28.5, 4.0),
)
# Group 3: Unions & Intersections
g_uni = d.add(
NodeGroup(title="代数的 Union & Intersection", padding=4.5),
xy=(122.0, 4.0),
)
g_uni.add(
Node("ZodUnion<Options>\nz.union([...]) / .or()", width=46, height=12.5, icon=PhosphorIcon.GIT_FORK, icon_size=5.5, card_style=Styles.PrimaryNeutral),
xy=(27.5, 49.0),
)
g_uni.add(
Node("ZodDiscriminatedUnion\nz.discriminatedUnion(d, opts)", width=46, height=12.5, icon=PhosphorIcon.LIGHTNING, icon_size=5.5, card_style=Styles.PrimaryNeutral),
xy=(27.5, 34.0),
)
g_uni.add(
Node("ZodXor<Options>\nz.xor([...]) (排他的 1 分岐)", width=46, height=12.5, icon=PhosphorIcon.SPLIT_HORIZONTAL, icon_size=5.5, card_style=Styles.SecondaryNeutral),
xy=(27.5, 19.0),
)
g_uni.add(
Node("ZodIntersection<A, B>\nz.intersection(a, b) / .and()", width=46, height=12.5, icon=PhosphorIcon.INTERSECT, icon_size=5.5, card_style=Styles.Neutral),
xy=(27.5, 4.0),
)
d.draw(xy=(4.0, 2.0))
# Top-down tree bus from ZodType root (center x=92, bottom y=79.5) to the top of each group (y=68.5)
line((92.0, 79.5), (92.0, 74.5), style=Styles.PrimaryBold)
line((33.5, 74.5), (153.5, 74.5), style=Styles.PrimaryBold)
line((33.5, 74.5), (33.5, 68.5), arrow_head="->", style=Styles.PrimaryBold)
line((93.5, 74.5), (93.5, 68.5), arrow_head="->", style=Styles.PrimaryBold)
line((153.5, 74.5), (153.5, 68.5), arrow_head="->", style=Styles.PrimaryBold)
canvas.save()
classZodObject#
ZodObject<Shape, Config> は、プレーンな JavaScript オブジェクトをプロパティ Shape マップ (Record<string, $ZodType>) に対して検証します。Zod v4 では .shape の遅延プロパティディスクリプタ解決と、高速パス JIT コンパイル ($ZodObjectJIT) が採用されています。
interface ZodObject<
out Shape extends core.$ZodShape = core.$ZodLooseShape,
out Config extends core.$ZodObjectConfig = core.$strip,
> extends _ZodType<core.$ZodObjectInternals<Shape, Config>>, core.$ZodObject<Shape, Config>
| プロパティ / メソッド | シグネチャ | 説明 |
|---|---|---|
.shape |
Shape |
オブジェクトを定義する生のプロパティスキーマ辞書を返します。 |
.keyof() |
() => ZodEnum<ToEnum<keyof Shape & string>> |
.shape 内の全文字列キーからなる ZodEnum を返します (z.keyof(schema) も利用可)。 |
.extend(shape) |
<U extends $ZodLooseShape>(shape: U) => ZodObject<Extend<Shape, U>, Config> |
オブジェクトスキーマを複製し、shape のプロパティをマージ・上書きします (非推奨の .merge() を置換)。 |
.safeExtend(shape) |
<U>(shape: SafeExtendShape<Shape, U>) => ZodObject<Extend<Shape, U>, Config> |
.extend() と同様ですが、既存プロパティを上書きする場合は新しい型が既存の入出力型に代入可能であることをコンパイル時に強制します。 |
.pick(mask) |
<M extends Mask<keyof Shape>>(mask: M) => ZodObject<Pick<Shape, ...>, Config> |
mask[k] が true のキーのみを抽出した新しい ZodObject を生成します。 |
.omit(mask) |
<M extends Mask<keyof Shape>>(mask: M) => ZodObject<Omit<Shape, ...>, Config> |
mask[k] が true のキーを除外した新しい ZodObject を生成します。 |
.partial(mask?) |
(mask?: Mask<keyof Shape>) => ZodObject<...> |
全プロパティ(または mask 指定キー)を ZodOptional でラップします(キー省略および undefined 値を許容)。 |
.exactPartial(mask?) |
(mask?: Mask<keyof Shape>) => ZodObject<...> |
全プロパティ(または mask 指定キー)を ZodExactOptional でラップします(キー自体の省略は許容し、明示的な { key: undefined } は拒否)。 |
.required(mask?) |
(mask?: Mask<keyof Shape>) => ZodObject<...> |
全プロパティ(または mask 指定キー)を ZodNonOptional でラップします。 |
.catchall(schema) |
<T extends SomeType>(schema: T) => ZodObject<Shape, $catchall<T>> |
未定義(未知)のすべてのキーを schema で検証します。 |
.strict() / .loose() / .strip() |
() => ZodObject<Shape, $strict | $loose | $strip> |
未知キーのポリシーを拒否 (catchall: z.never())、パススルー (catchall: z.unknown())、または除去 (catchall: undefined) に切り替えます。 |
import { z } from "zod";
const BaseUser = z.object({
id: z.uuid(),
email: z.email(),
name: z.string(),
});
// extend, pick, omit, partial コンビネータ
const AdminUser = BaseUser.extend({ permissions: z.array(z.string()) });
const PublicProfile = BaseUser.omit({ email: true });
const PatchUser = BaseUser.partial({ name: true, email: true });
functionz.object / z.strictObject / z.looseObject#
Zod v4 では、未知キーに対する3種類のポリシーに対応する専用トップレベルコンストラクタが提供されています。
function z.object<T extends core.$ZodLooseShape>(shape?: T, params?: string | core.$ZodObjectParams): ZodObject<util.Writeable<T>, core.$strip>
function z.strictObject<T extends core.$ZodLooseShape>(shape: T, params?: string | core.$ZodObjectParams): ZodObject<util.Writeable<T>, core.$strict>
function z.looseObject<T extends core.$ZodLooseShape>(shape: T, params?: string | core.$ZodObjectParams): ZodObject<util.Writeable<T>, core.$loose>
| コンストラクタ | Config モード | 未知キーの挙動 | JSON Schema additionalProperties |
|---|---|---|---|
z.object(shape, params?) |
core.$strip |
パース結果のオブジェクトから未知のプロパティを静かに除去します。 | false (toJSONSchema のデフォルト) |
z.strictObject(shape, params?) |
core.$strict |
入力に未知のキーが含まれる場合、unrecognized_keys Issue を発行します。 |
false |
z.looseObject(shape, params?) |
core.$loose |
未知のプロパティをそのまま出力オブジェクトに保持します ([k: string]: unknown)。 |
{} (または省略) |
import { z } from "zod";
const StrictPayload = z.strictObject({ action: z.literal("login") });
StrictPayload.safeParse({ action: "login", extra: 123 }).success; // => false (unrecognized_keys)
const LoosePayload = z.looseObject({ action: z.literal("login") });
LoosePayload.parse({ action: "login", traceId: "abc" }); // => { action: "login", traceId: "abc" }
classZodArray#
Array.isArray(input) を検証し、各要素を element: T でパースする ZodArray<T> スキーマを構築します。
function z.array<T extends core.SomeType>(element: T, params?: string | core.$ZodArrayParams): ZodArray<T>
| プロパティ / メソッド | シグネチャ | 説明 |
|---|---|---|
.element / .unwrap() |
T / () => T |
内部要素スキーマ T を返します。 |
.min(n, params?) / .max(n, params?) |
(len: number, params?) => this |
input.length >= n (too_small) または input.length <= n (too_big) を検証します。 |
.length(n, params?) |
(len: number, params?) => this |
配列長が厳密に input.length === n であることを検証します。 |
.nonempty(params?) |
(params?) => this |
.min(1, params) と同等です。注:Zod v4 では .nonempty() の推論型は [T, ...T[]] ではなく T[] を維持します(非空タプル型が必要な場合は z.tuple([T], T) を使用してください)。 |
import { z } from "zod";
const Tags = z.array(z.string().min(1)).min(1).max(10);
classZodTuple#
各インデックス位置のスキーマと、任意の可変長 rest 要素スキーマを持つ固定長 ZodTuple<T, Rest> スキーマを構築します。
function z.tuple<T extends readonly [core.SomeType, ...core.SomeType[]]>(items: T, params?: string | core.$ZodTupleParams): ZodTuple<T, null>
function z.tuple<T extends readonly [core.SomeType, ...core.SomeType[]], Rest extends core.SomeType>(
items: T,
rest: Rest,
params?: string | core.$ZodTupleParams
): ZodTuple<T, Rest>
| メソッド | シグネチャ | 説明 |
|---|---|---|
.rest(restSchema) |
<R extends SomeType>(rest: R) => ZodTuple<T, R> |
末尾の後続要素に対する可変長 Rest スキーマを追加します ([...T, ...R[]])。 |
.partial() |
() => ZodTuple<{ [K in keyof T]: ZodOptional<T[K]> }, Rest> |
各固定タプル要素を ZodOptional でラップします。 |
import { z } from "zod";
const Coordinate = z.tuple([z.number(), z.number()], z.string());
type Coord = z.infer<typeof Coordinate>; // [number, number, ...string[]]
classZodRecord#
Key-Value 辞書オブジェクトを検証する ZodRecord<Key, Value> スキーマを構築します。Zod v4 では、網羅的レコード (z.record)、部分キーレコード (z.partialRecord)、およびパススルーレコード (z.looseRecord) が明確に区別されます。
function z.record<Key extends core.$ZodRecordKey, Value extends core.SomeType>(
keyType: Key,
valueType: Value,
params?: string | core.$ZodRecordParams
): ZodRecord<Key, Value>
function z.partialRecord<Key extends core.$ZodRecordKey, Value extends core.SomeType>(
keyType: Key,
valueType: Value,
params?: string | core.$ZodRecordParams
): ZodRecord<Key & core.$partial, Value>
function z.looseRecord<Key extends core.$ZodRecordKey, Value extends core.SomeType>(
keyType: Key,
valueType: Value,
params?: string | core.$ZodRecordParams
): ZodRecord<Key, Value>
| コンストラクタ | キー検証の挙動 | Key = z.enum(["a", "b"]) の推論型 |
|---|---|---|
z.record(keyType, valueType) |
網羅的 (Exhaustive):有限のリテラル / Enum キーがすべてオブジェクト上に存在することを要求します。 | Record<"a" | "b", V> ({ a: V; b: V }) |
z.partialRecord(keyType, valueType) |
非網羅的 (Partial):存在するキーのみを keyType & valueType で検証し、全 Enum キーの存在を強制しません。 |
Partial<Record<"a" | "b", V>> ({ a?: V; b?: V }) |
z.looseRecord(keyType, valueType) |
keyType のパターンに一致するキーのみを valueType で検証し、一致しないキーはそのまま通過させます。 |
Record<K, V> & Record<string, unknown> |
import { z } from "zod";
const EnvMap = z.record(z.string(), z.string());
const LocaleOverrides = z.partialRecord(z.enum(["en", "ja", "de"]), z.string());
classZodMap & ZodSet#
ES6 ネイティブの Map<K, V> および Set<T> インスタンスを .size 制約付きで検証します。
function z.map<Key extends core.SomeType, Value extends core.SomeType>(
keyType: Key,
valueType: Value,
params?: string | core.$ZodMapParams
): ZodMap<Key, Value>
function z.set<Value extends core.SomeType>(
valueType: Value,
params?: string | core.$ZodSetParams
): ZodSet<Value>
| プロパティ / メソッド | 対象クラス | 説明 |
|---|---|---|
.keyType / .valueType |
ZodMap |
キースキーマおよび値スキーマを参照します。 |
.min(n, params?) / .max(n, params?) |
ZodMap, ZodSet |
input.size >= n (too_small) または input.size <= n (too_big) を検証します。 |
.size(n, params?) |
ZodMap, ZodSet |
エントリ数が厳密に input.size === n であることを検証します。 |
.nonempty(params?) |
ZodMap, ZodSet |
.min(1, params) と同等です。 |
import { z } from "zod";
const UniqueIds = z.set(z.uuid()).nonempty().max(100);
classZodUnion & ZodXor#
z.union(options) は包含的 OR ユニオン (A | B、最初に一致した分岐の出力を返却) を構築し、z.xor(options) は排他的 XOR ユニオン(ただ1つの分岐のみが一致した場合にのみ成功)を構築します。
function z.union<const T extends readonly core.SomeType[]>(options: T, params?: string | core.$ZodUnionParams): ZodUnion<T>
function z.xor<const T extends readonly core.SomeType[]>(options: T, params?: string | core.$ZodXorParams): ZodXor<T>
| クラス / メソッド | シグネチャ | 説明 |
|---|---|---|
z.union(options, params?) / a.or(b) |
ZodUnion<T> |
options を順番に評価し、最初に成功したスキーマの出力を返すか invalid_union を発行します。 |
z.xor(options, params?) |
ZodXor<T> |
全分岐を評価し、成功した分岐が 0 個または 2 個以上の場合は invalid_union (inclusive: false) で失敗します。 |
.options |
T |
構成メンバースキーマの読み取り専用タプルです。 |
import { z } from "zod";
// 排他的 Union:`id` または `slug` のどちらか一方のみを許容(両方指定はエラー)
const LookupFilter = z.xor([
z.strictObject({ id: z.uuid() }),
z.strictObject({ slug: z.string() }),
]);
classZodDiscriminatedUnion#
共有ディスクリミネータプロパティ (discriminator: Disc) をインデックスとして O(1) ルックアップを行うタグ付き Union を構築します。Zod v4 の z.discriminatedUnion は、ネストした Discriminated Union、パイプ、複数値リテラルもディスクリミネータとして合成可能です。
function z.discriminatedUnion<
Types extends readonly [core.$ZodTypeDiscriminable, ...core.$ZodTypeDiscriminable[]],
Disc extends string,
>(
discriminator: Disc,
options: Types,
params?: string | core.$ZodDiscriminatedUnionParams
): ZodDiscriminatedUnion<Types, Disc>
import { z } from "zod";
const WebhookEvent = z.discriminatedUnion("type", [
z.object({ type: z.literal("invoice.paid"), amount: z.int() }),
z.object({ type: z.literal("invoice.failed"), reason: z.string() }),
]);
classZodIntersection#
入力を left と right の両方のスキーマでパースし、出力をディープマージする論理 AND 交差型 (A & B) を構築します (z.intersection(a, b) または a.and(b))。
function z.intersection<T extends core.SomeType, U extends core.SomeType>(left: T, right: U): ZodIntersection<T, U>
[!TIP] 2つの
ZodObjectスキーマを結合する場合は、z.intersection(A, B)よりもA.extend(B.shape)を優先してください。.extend()はフラットなZodObjectを生成するため、.keyof()、.pick()、.omit()、および高速な JIT オブジェクトコンパイルがそのまま利用できます。
classZodOptional & ZodNullable#
ラッパーコンビネータは、内部スキーマ T の前後で undefined、null、デフォルト値、およびパース失敗のフローを制御します。
Source Code
from drawlib import canvas
from drawlib.diagrams.flow import Decision, FlowDiagram, Process, Start
from drawlib.styles import Styles
from drawlib.text import text
canvas.clear()
canvas.setup(width=184, height=84, dpi=150)
text(
(92, 79.0),
"Zod v4 ラッパーコンビネータ実行フロー (Prefault vs Default & Catch)",
style=Styles.DarkBold.patch(text_size=12.5),
)
flow = FlowDiagram(
node_style=Styles.Neutral,
edge_style=Styles.PrimaryBold,
edge_text_style=Styles.DarkBold.patch(text_size=10.0),
)
n_in = flow.add(
Start(
"生入力 (data)\nparse(data)",
width=28,
height=12,
style=Styles.PrimaryFlat,
text_style=Styles.WhiteBold.patch(text_size=10.0),
),
xy=(16.0, 42.0),
)
d_undef = flow.add(
Decision(
"data ===\nundefined?",
width=28,
height=16,
style=Styles.PrimaryNeutral,
text_style=Styles.DarkBold.patch(text_size=10.0),
),
xy=(54.0, 42.0),
)
n_default = flow.add(
Process(
"ZodDefault / ZodOptional\n内部パースを短絡スキップ!\ndefaultValue / undefined 返却",
width=48,
height=14,
style=Styles.SecondaryNeutral,
text_style=Styles.DarkBold.patch(text_size=10.0),
),
xy=(104.0, 62.0),
)
n_prefault = flow.add(
Process(
"ZodPrefault(initVal)\ndata = initVal を代入し\ninnerType を実行!",
width=44,
height=14,
style=Styles.PrimaryNeutral,
text_style=Styles.DarkBold.patch(text_size=10.0),
),
xy=(54.0, 12.0),
)
n_inner = flow.add(
Process(
"内部スキーマ (innerType)\nバリデーション & Transform\n(null 時は ZodNullable)",
width=48,
height=14,
style=Styles.Neutral,
text_style=Styles.DarkBold.patch(text_size=10.0),
),
xy=(104.0, 32.0),
)
n_out = flow.add(
Process(
"ZodCatch / ZodReadonly\nエラー時 -> catchValue(ctx)\n成功時 -> Object.freeze / $brand",
width=44,
height=16,
style=Styles.AccentFlat,
text_style=Styles.WhiteBold.patch(text_size=10.0),
),
xy=(156.0, 46.0),
)
flow.connect(n_in, d_undef)
flow.connect(d_undef, n_default, label="Yes (default)", start_side="top", end_side="left")
flow.connect(d_undef, n_prefault, label="Yes (prefault)", start_side="bottom", end_side="top")
flow.connect(d_undef, n_inner, label="No", start_side="right", end_side="left")
flow.connect(n_prefault, n_inner, start_side="right", end_side="bottom")
flow.connect(n_default, n_out, start_side="right", end_side="top")
flow.connect(n_inner, n_out, start_side="right", end_side="bottom")
flow.draw(xy=(2.0, 2.0))
canvas.save()
function z.optional<T extends core.SomeType>(innerType: T): ZodOptional<T>
function z.exactOptional<T extends core.SomeType>(innerType: T): ZodExactOptional<T>
function z.nullable<T extends core.SomeType>(innerType: T): ZodNullable<T>
function z.nullish<T extends core.SomeType>(innerType: T): ZodOptional<ZodNullable<T>>
function z.nonoptional<T extends core.SomeType>(innerType: T, params?: string | core.$ZodNonOptionalParams): ZodNonOptional<T>
| ラッパークラス / 関数 | z.input<S> |
z.output<S> |
挙動 & .unwrap() |
|---|---|---|---|
ZodOptional<T> (.optional()) |
Input<T> | undefined |
Output<T> | undefined |
入力が undefined の場合に短絡評価し、undefined を返します。.unwrap() で内部スキーマを取得します。 |
ZodExactOptional<T> (.exactOptional()) |
Input<T> (キー省略可) |
Output<T> (キー省略可) |
ZodObject 内でプロパティキー自体の省略は許可しますが、明示的な { key: undefined } は拒否します。 |
ZodNullable<T> (.nullable()) |
Input<T> | null |
Output<T> | null |
入力が null の場合に短絡評価し、null を返します。.unwrap() で内部スキーマを取得します。 |
z.nullish(schema) (.nullish()) |
Input<T> | null | undefined |
Output<T> | null | undefined |
z.optional(z.nullable(schema)) と同等です。 |
ZodNonOptional<T> (.nonoptional()) |
Exclude<Input<T>, undefined> |
Exclude<Output<T>, undefined> |
innerType が ZodOptional や ZodUnknown であっても undefined を拒否します。 |
classZodDefault & ZodPrefault#
Zod v4 では、出力側で短絡評価するデフォルト (ZodDefault) と、入力側でパース前に注入するデフォルト (ZodPrefault) の両方が提供されます。
function z._default<T extends core.SomeType>(
innerType: T,
defaultValue: util.NoUndefined<core.output<T>> | (() => util.NoUndefined<core.output<T>>)
): ZodDefault<T>
function z.prefault<T extends core.SomeType>(
innerType: T,
defaultValue: core.input<T> | (() => core.input<T>)
): ZodPrefault<T>
| 機能 | schema.default(valueOrFn) (ZodDefault<T>) |
schema.prefault(valueOrFn) (ZodPrefault<T>) |
|---|---|---|
| デフォルト値の型 | z.output<T> (Transform 後の出力型) |
z.input<T> (Transform 前の生入力型) |
undefined 時の実行挙動 |
innerType を短絡スキップ:内部チェックや Transform を実行せず即座に defaultValue を返します。 |
defaultValue を innerType に入力:内部チェック・Refinement・Transform をすべて実行します。 |
| ミュータブル値の安全性 | パースごとにオブジェクト/配列の浅いコピーを返すか、() => defaultValue を呼び出します。 |
パースごとにオブジェクト/配列の浅いコピーを返すか、() => defaultValue を呼び出します。 |
import { z } from "zod";
const TrimmedWithDefault = z.string().trim().default("guest");
TrimmedWithDefault.parse(undefined); // => "guest" (短絡返却)
const TrimmedWithPrefault = z.string().trim().prefault(" guest ");
TrimmedWithPrefault.parse(undefined); // => "guest" (innerType でパース & trim 実行!)
classZodCatch & ZodReadonly#
エラー回復フォールバック (ZodCatch)、真偽値への成功判定変換 (ZodSuccess)、イミュータブル凍結 (ZodReadonly)、および公称型ブランディング ($ZodBranded) を提供します。
function z.catch<T extends core.SomeType>(
innerType: T,
catchValue: core.output<T> | ((ctx: core.$ZodCatchCtx) => core.output<T>)
): ZodCatch<T>
function z.readonly<T extends core.SomeType>(innerType: T): ZodReadonly<T>
function z.success<T extends core.SomeType>(innerType: T): ZodSuccess<T>
| コンビネータ | 戻り値型 | ランタイム & 型レベルの挙動 |
|---|---|---|
schema.catch(valOrFn) |
ZodCatch<this> |
innerType の検証が失敗した場合にエラーを抑制し、valOrFn({ error, input, issues, value }) を返します。 |
schema.readonly() |
ZodReadonly<this> |
実行時に Object.freeze(output) を呼び出し、出力型を Readonly<Output<T>> (readonly T[], ReadonlyMap, ReadonlySet) にラップします。 |
z.success(schema) |
ZodSuccess<T> |
schema で入力をパースし、成否を表す boolean (true / false) を返します。 |
schema.brand<Name, Dir?>() |
core.$ZodBranded<this, Name, Dir> |
ランタイムオーバーヘッドなしの公称型ブランドを付与します (Dir = "out" デフォルト、"in"、または "inout")。 |
import { z } from "zod";
const SafeRetryCount = z.int().min(0).catch((ctx) => {
console.warn("Invalid retry count, falling back to 3:", ctx.error.issues);
return 3;
});
const UserId = z.uuid().brand<"UserId">();
type UserId = z.infer<typeof UserId>; // string & z.$brand<"UserId">
functionz.lazy & z.custom#
遅延評価による再帰スキーマ (z.lazy)、任意の TypeScript 型述語 (z.custom)、クラスインスタンス検証 (z.instanceof)、および再帰 JSON 値スキーマ (z.json) を提供します。
[!TIP] Zod v4 のネイティブ再帰オブジェクト:ほとんどの再帰オブジェクトや配列では
z.lazy()が不要になりました。z.object({ get subcategories() { return z.array(Category); } })のように getter プロパティを使用するだけで、手動のz.ZodType型注釈なしに完全な静的型推論が機能します。トップレベルの相互再帰 Union などを定義する場合にz.lazy(() => ...)を使用してください。
function z.lazy<T extends core.SomeType>(getter: () => T): ZodLazy<T>
function z.custom<O>(fn?: (data: unknown) => unknown, params?: string | core.$ZodCustomParams): ZodCustom<O, O>
function z.instanceof<T extends typeof util.Class>(cls: T, params?: ZodInstanceOfParams): ZodInstanceOf<InstanceType<T>>
function z.json(params?: string | core.$ZodCustomParams): ZodJSONSchema
| コンストラクタ | 主なメソッド / 引数 | 説明 |
|---|---|---|
z.lazy(getter) |
.unwrap(): T |
初回パース時または JSON Schema 走査時に getter() を遅延評価します。 |
z.custom<T>(predicate?, params?) |
fn: (data: unknown) => boolean | Promise<boolean> |
predicate 関数で検証される ZodCustom<T, T> スキーマを生成します(デフォルトで abort: true)。 |
z.instanceof(Class, params?) |
.properties(shape, params?) |
data instanceof Class を検証し、オプションで .properties({ ... }) によりインスタンスプロパティも検証します。 |
z.json(params?) |
ZodJSONSchema (util.JSONType) |
任意の有効な JSON 値 (string | number | boolean | null | JSONType[] | { [k: string]: JSONType }) に一致する組み込み再帰スキーマです。 |
import { z } from "zod";
// Zod v4 のネイティブ getter 再帰(z.lazy のボイラープレート不要)
const Category = z.object({
name: z.string(),
get children() {
return z.array(Category);
},
});
classZodFunction & ZodPromise#
z.function() は、ラップされた関数が呼び出されるたびに引数と戻り値を実行時検証する関数ラッパー (ZodFunction<Args, Returns>) を構築します。z.promise(schema) は入力が Promise であることを確認し、解決された値をパースします。
function z.function<In extends core.$ZodFunctionIn, Out extends core.$ZodType>(params?: {
input?: In | ReadonlyArray<core.$ZodType>;
output?: Out;
}): ZodFunction<In, Out>
function z.promise<T extends core.SomeType>(innerType: T): ZodPromise<T>
ZodFunction メソッド |
シグネチャ | 説明 |
|---|---|---|
.input(tupleOrArray, rest?) |
(args: TupleItems | ZodTuple) => ZodFunction |
引数タプルスキーマを設定または置換します。 |
.output(returnSchema) |
(output: $ZodType) => ZodFunction |
戻り値スキーマを設定または置換します。 |
.implement(fn) |
(fn: InnerFn) => OuterFn |
同期または非同期の fn をラップし、呼び出しごとに引数と戻り値の両方を検証します。 |
.implementAsync(fn) |
(fn: AsyncInnerFn) => AsyncOuterFn |
Promise を返す非同期関数実装を明示的にラップします。 |
import { z } from "zod";
const ComputeTax = z.function({
input: [z.number().nonnegative(), z.number().min(0).max(1)],
output: z.number().nonnegative(),
});
const calc = ComputeTax.implement((amount, rate) => amount * rate);
calc(100, 0.08); // => 8