mcpField
Z
zod

zod

github.com/marcioaltoe開発061 回インストール1 日前に更新
リポジトリ

zod について

Zodは、実行時のデータ検証と型推論を必要とする開発者向けのTypeScriptファーストなスキーマ検証ライブラリです。解析、変換、JSON Schemaとの相互変換に対応し、ツリーシェイク向けのMini版も用意されています。

主な機能

  1. 01実行時の解析と検証
  2. 02スキーマからの型推論
  3. 03変換と双方向コーデック
  4. 04JSON Schemaの入出力
  5. 05ツリーシェイク対応のZod Mini

活用シーン

  1. 01実行時の入力データ検証
  2. 02スキーマからのTypeScript型推論
  3. 03JSON Schemaとの相互変換

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/marcioaltoe/skills --skill zod

インストール後、Claude Code で/zodを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
references/
advanced.md
codecs.md
json-schema.md
migration.md
zod-mini.md

詳細

Zod 4

TypeScript を優先したスキーマ検証。コアバンドルは 2kb(gzip 圧縮時)。依存関係はありません。

重要:現在の安定版は Zod 4(zod@^4.0.0)です。常に Zod 4 のコードを記述してください。非推奨の Zod 3 のパターンは使用しないでください。

インポート

import * as z from "zod";

ツリーシェイキング可能なバリアント(バンドルサイズがより小さいもの)を使用する場合:

import * as z from "zod/mini";

基本パターン

パース
schema.parse(data);           // throws ZodError on failure
schema.safeParse(data);       // returns { success, data?, error? }
await schema.parseAsync(data);
await schema.safeParseAsync(data);
型推論
type MyType = z.infer<typeof mySchema>;    // output type
type MyInput = z.input<typeof mySchema>;   // input type
type MyOutput = z.output<typeof mySchema>; // same as z.infer
プリミティブ
z.string();
z.number();      // finite numbers only (no Infinity, no NaN)
z.bigint();
z.boolean();
z.symbol();
z.undefined();
z.null();
z.date();
z.nan();
型強制
z.coerce.string();    // String(input)
z.coerce.number();    // Number(input)
z.coerce.boolean();   // Boolean(input)
z.coerce.bigint();    // BigInt(input)
z.coerce.date();      // new Date(input)

文字列形式(トップレベル)

メソッドではなく、トップレベル関数を使用してください。z.string().email() のようなメソッドは非推奨です。

// CORRECT (Zod 4)
z.email();
z.uuid();
z.url();
z.httpUrl();
z.hostname();
z.emoji();
z.base64();
z.base64url();
z.hex();
z.jwt();
z.nanoid();
z.cuid();
z.cuid2();
z.ulid();
z.ipv4();
z.ipv6();
z.mac();
z.cidrv4();
z.cidrv6();
z.hash("sha256");     // "sha1" | "sha384" | "sha512" | "md5"
z.e164();              // phone numbers
z.iso.date();
z.iso.time();
z.iso.datetime();
z.iso.duration();

// DEPRECATED (Zod 3 style — do NOT use)
z.string().email();    // ❌
z.string().uuid();     // ❌
z.string().url();      // ❌
UUID のバージョン
z.uuid();                    // any RFC 9562/4122 UUID
z.uuid({ version: "v4" });  // specific version
z.uuidv4();                  // convenience
z.uuidv6();
z.uuidv7();
z.guid();                    // any 8-4-4-4-12 hex pattern (less strict)
カスタムメール正規表現
z.email();                                     // default (Gmail rules)
z.email({ pattern: z.regexes.html5Email });    // browser-style
z.email({ pattern: z.regexes.rfc5322Email });  // RFC 5322
z.email({ pattern: z.regexes.unicodeEmail });  // intl emails
JWT
z.jwt();
z.jwt({ alg: "HS256" });

数値と整数

z.number();      // any finite number
z.int();         // safe integer range
z.int32();       // int32 range
z.float32();     // float32 range
z.float64();     // float64 range

// bigint variants
z.bigint();
z.int64();
z.uint64();
数値の検証
z.number().gt(5);
z.number().gte(5);          // alias: .min(5)
z.number().lt(5);
z.number().lte(5);          // alias: .max(5)
z.number().positive();
z.number().nonnegative();
z.number().negative();
z.number().nonpositive();
z.number().multipleOf(5);   // alias: .step(5)
文字列の検証
z.string().max(5);
z.string().min(5);
z.string().length(5);
z.string().regex(/pattern/);
z.string().startsWith("abc");
z.string().endsWith("xyz");
z.string().includes("---");
z.string().uppercase();
z.string().lowercase();
z.string().trim();
z.string().toLowerCase();
z.string().toUpperCase();
z.string().normalize();

オブジェクト

z.object({ name: z.string(), age: z.number() });          // strips unknown keys
z.strictObject({ name: z.string() });                      // errors on unknown keys
z.looseObject({ name: z.string() });                       // passes unknown keys through

非推奨:.strict()、.passthrough()、.strip()、.merge()、.deepPartial()。

オブジェクトのメソッド
schema.extend({ newField: z.string() });    // add fields
schema.pick({ name: true });                // pick fields
schema.omit({ age: true });                 // omit fields
schema.partial();                           // all optional
schema.partial({ name: true });             // some optional
schema.required();                          // all required
schema.keyof();                             // ZodEnum from keys
schema.shape.name;                          // access inner schema

tsc のパフォーマンスを最大限に高めるには、スプレッド構文を推奨します:

z.object({ ...Base.shape, ...Extra.shape, newField: z.string() });
再帰オブジェクト
const Category = z.object({
  name: z.string(),
  get subcategories() {
    return z.array(Category);
  },
});

列挙型

z.enum(["A", "B", "C"]);               // string enum
z.enum(MyTSEnum);                       // TypeScript enum (replaces z.nativeEnum())
z.enum({ A: 0, B: 1 } as const);       // enum-like object

非推奨:z.nativeEnum()。代わりに z.enum() を使用してください。

配列、タプル、セット、マップ

z.array(z.string());
z.array(z.string()).min(1).max(10).length(5);
z.tuple([z.string(), z.number()]);
z.tuple([z.string()], z.number());    // variadic: [string, ...number[]]
z.set(z.number());
z.map(z.string(), z.number());

ユニオンとインターセクション

z.union([z.string(), z.number()]);
z.discriminatedUnion("status", [
  z.object({ status: z.literal("ok"), data: z.string() }),
  z.object({ status: z.literal("err"), error: z.string() }),
]);
z.xor([z.string(), z.number()]);          // exclusive union (exactly one match)
z.intersection(schemaA, schemaB);

レコード

z.record(z.string(), z.number());                    // Record<string, number>
z.record(z.enum(["a", "b"]), z.string());            // exhaustive: { a: string; b: string }
z.partialRecord(z.enum(["a", "b"]), z.string());     // partial: { a?: string; b?: string }
z.looseRecord(z.string().regex(/^x_/), z.number());  // pass through non-matching keys

破壊的変更:引数を 1 つだけ渡す z.record(z.string()) の形式は削除されました。キーと値の両方のスキーマを必ず渡してください。

リテラル

z.literal("hello");
z.literal(42);
z.literal(true);
z.literal(["a", "b", "c"]);   // multi-value literal (new in Zod 4)

ファイル

z.file();
z.file().min(10_000);                          // min size in bytes
z.file().max(1_000_000);                       // max size in bytes
z.file().mime("image/png");                    // single MIME
z.file().mime(["image/png", "image/jpeg"]);    // multiple MIMEs

Stringbool

z.stringbool();    // "true"/"yes"/"1"/"on"/"y"/"enabled" → true, inverses → false
z.stringbool({ truthy: ["yes", "y"], falsy: ["no", "n"] });
z.stringbool({ case: "sensitive" });

テンプレートリテラル

z.templateLiteral(["hello, ", z.string()]);                    // `hello, ${string}`
z.templateLiteral([z.number(), z.enum(["px", "em", "rem"])]);  // `${number}px` | ...

オプショナル、Nullable、デフォルト値

z.optional(z.string());          // or z.string().optional()
z.nullable(z.string());          // or z.string().nullable()
z.nullish(z.string());           // optional + nullable

z.string().default("hello");     // short-circuits on undefined, returns output type
z.string().prefault("hello");    // pre-parse default, runs through validation
z.number().catch(42);            // fallback on any validation error

破壊的変更:.default() が受け取るのは入力型ではなく出力型になりました。以前の動作には .prefault() を使用してください。

変換とパイプ

z.transform((val) => String(val));                      // standalone transform
z.string().transform((val) => val.length);              // pipe string → transform
z.preprocess((val) => String(val), z.string());         // transform → pipe to schema
z.string().pipe(z.transform((val) => val.length));      // explicit pipe

// .overwrite() — transform without changing inferred type
z.number().overwrite((val) => val ** 2);

Codec(双方向変換)

Zod 4.1 で追加されました。エンコードとデコードのペアを定義します:

const stringToDate = z.codec(z.iso.datetime(), z.date(), {
  decode: (s) => new Date(s),
  encode: (d) => d.toISOString(),
});

stringToDate.decode("2024-01-15T10:30:00.000Z");  // → Date
stringToDate.encode(new Date());                    // → string
stringToDate.parse("2024-01-15T10:30:00.000Z");    // → Date (same as decode at runtime)

エラーのカスタマイズ

統一された error パラメーターを使用してください(message、errorMap、invalid_type_error、required_error を置き換えます):

z.string().min(5, { error: "Too short" });
z.string({ error: (issue) => issue.input === undefined ? "Required" : "Not a string" });
z.string({ error: (issue) => {
  if (issue.code === "too_small") return `Min ${issue.minimum}`;
}});

非推奨:message、errorMap、invalid_type_error、required_error。

メタデータとレジストリ

z.string().meta({ id: "email", title: "Email", description: "User email" });
z.string().describe("A description");      // shorthand for .meta({ description: ... })

// Custom registries
const myReg = z.registry<{ description: string }>();
z.string().register(myReg, { description: "..." });

JSON Schema

z.toJSONSchema(schema);                                        // Zod → JSON Schema
z.toJSONSchema(schema, { target: "draft-07" });                // specific draft
z.toJSONSchema(schema, { target: "openapi-3.0" });             // OpenAPI 3.0
z.fromJSONSchema(jsonSchema);                                  // JSON Schema → Zod (experimental)

リファインメント

z.string().refine((val) => val.includes("@"), { error: "Must contain @" });
z.string().refine((val) => val.includes("@"), { error: "...", abort: true }); // stop on failure
z.array(z.string()).superRefine((val, ctx) => {
  ctx.addIssue({ code: "custom", message: "...", input: val });
});

リファインメントはスキーマ内に含まれるようになりました(ZodEffects でラップされません)。.refine() とほかのメソッドを交互に使用できます:

z.string().refine(v => v.includes("@")).min(5);  // works in Zod 4!

エラーの整形出力

z.prettifyError(zodError);   // formatted multi-line string
z.treeifyError(zodError);    // tree structure (replaces .format() and .flatten())

参考資料

  • Zod Mini:ツリーシェイキング可能な API の違い、.check() の使い方、バンドルサイズのトレードオフについては、references/zod-mini.md を参照してください
  • Codec:双方向変換、エンコード時の動作、一般的な Codec パターン(stringToDate、jsonCodec など)については、references/codecs.md を参照してください
  • JSON Schema:z.toJSONSchema() のオプション、形式の変換、レジストリベースの複数スキーマ、z.fromJSONSchema() については、references/json-schema.md を参照してください
  • 高度なパターン:レジストリ、リファインメントの when、.superRefine()、.check()、関数、ブランド型、読み取り専用、カスタムスキーマ、高度な文字列/オブジェクト/レコード/ユニオンのオプションについては、references/advanced.md を参照してください
  • Zod 3 からの移行:すべての破壊的変更と非推奨 API については、references/migration.md を参照してください

コメント