Zod 4 の歩き方 - 型と実行時バリデーションをつなぐ、LLM出力検証まで

Zod 4 の歩き方 - 型と実行時バリデーションをつなぐ、LLM出力検証まで

作成日:
更新日:

TypeScript の型はコンパイル時の保証です。でも、フォーム入力・API レスポンス・環境変数・LLM の出力——こうした「外から来るデータ」は、実行時にどんな形でやってくるか分かりません。ここを埋めるのが Zod のような実行時バリデーションで、スキーマを1つ書けば「実行時の検証」と「TypeScript の型」が同時に手に入ります。

その Zod のメジャーバージョン Zod 4 は、速度・バンドルサイズ・API がまとめて見直された版です。この記事では、Zod 3 から何が変わったかと、フォーム・API 境界・LLM 出力検証での使いどころを整理します。「型だけでは守れない領域」を扱う点で、TypeScript 7 の高速化とは別軸の話です。

まず基本: スキーマが型と検証を兼ねる

Zod の肝は「スキーマを1つ書くと、検証関数と TypeScript 型が両方手に入る」ことです。

スキーマから型を導出する
import { z } from 'zod';
 
const User = z.object({
  name: z.string(),
  age: z.number().int().positive(),
  email: z.email(),
});
 
type User = z.infer<typeof User>; // { name: string; age: number; email: string }
 
const result = User.safeParse(input); // 実行時に検証
if (result.success) {
  result.data; // 型は User
}

z.infer で型を取り出せるので、型定義とバリデーションを二重に書かなくて済む。これが Zod の基本的な価値です。

Zod 4 で変わったこと

1. 大幅な高速化とバンドル削減

Zod 4 はまず速くなりました。公式の計測では Zod 3 比で、文字列のパースが約14.71倍、配列が約7.43倍、オブジェクトが約6.5倍。さらにコアのバンドルサイズが57%削減、後述の Zod Mini では85%削減です。バリデーションはホットパスに入りやすいので、この改善はそのまま効きます。

2. 文字列フォーマットがトップレベル関数に

z.string().email() のようなチェーンが、トップレベル関数に移りました。tree-shaking が効きやすくなります。

フォーマットはトップレベルへ
z.email();
z.uuid();
z.url();
z.ipv4();

従来の z.string().email() パターンの置き換えです。

3. エラー指定が error に統一

これまで message / invalid_type_error / required_error などに分かれていたエラー指定が、単一の error パラメータに統一されました。

エラーメッセージの指定
z.string().min(5, { error: 'short すぎます' });

4. メタデータと registry

Zod 4 では、メタデータをスキーマ自体ではなく「レジストリ」に持たせる設計になりました。.meta() で型付きのメタdata(タイトル・説明など)を付けられます。

メタデータを付ける
const Email = z.email().meta({
  title: 'Email address',
  description: 'ユーザーのメールアドレス',
});

5. JSON Schema 変換が標準で

z.toJSONSchema() で、Zod スキーマを JSON Schema に変換できるようになりました。.meta() で付けた情報も出力に含まれます。これが後述の LLM 出力検証で効きます。

6. Zod Mini

関数型 API の tree-shakable な派生版 Zod Minizod/mini)が用意されました。z.string().optional() の代わりに z.optional(z.string()) のように書きます。バンドルサイズを極限まで絞りたいフロントエンドで有効です。

NOTE

Zod Mini は「同じ Zod だが書き方が関数型」という関係です。チェーン記法に慣れているなら通常の Zod、バンドルサイズが最優先(widget や軽量 SPA など)なら Zod Mini、と使い分けます。両方を無理に混ぜる必要はありません。

使いどころ1: フォームと API 境界

一番の定番が「外から来るデータ」の検証です。

  • フォーム入力: 送信前にクライアントで検証し、エラーメッセージを出す
  • API 境界: サーバーが受け取った body や、クライアントが受け取ったレスポンスを safeParse で検証する
  • 環境変数: 起動時に process.env を検証し、設定ミスを早期に落とす

ポイントは、TypeScript の型は「自分のコードの中」しか守らないこと。ネットワークの向こうから来る JSON は、型注釈をいくら書いても実行時には保証されません。境界で Zod を一枚かませることで、「型どおりのはず」が「型どおりであることを検証済み」に変わります。

使いどころ2: LLM の構造化出力検証(今っぽい使い方)

2026年的な使い方が、LLM の出力検証です。LLM に「JSON で返して」と頼んでも、形がズレることがあります。ここで Zod が二重に効きます。

  1. スキーマから z.toJSONSchema() で JSON Schema を生成し、それを LLM に「この形で返して」と渡す(構造化出力の指定)
  2. 返ってきた JSON を同じ Zod スキーマで safeParse し、形が合っているか実行時に検証する
LLM 出力をスキーマで縛る
const Article = z.object({
  title: z.string(),
  tags: z.array(z.string()),
  summary: z.string(),
});
 
// 1. JSON Schema を生成して LLM に渡す
const jsonSchema = z.toJSONSchema(Article);
 
// 2. 返ってきた出力を検証
const parsed = Article.safeParse(llmOutput);
if (!parsed.success) {
  // 形が違う → リトライや修正にまわす
}

「1つのスキーマで、LLM への指示(JSON Schema)と、受け取りの検証(parse)の両方を賄える」のが効率的です。LangChain.jsのようなフレームワークでも、構造化出力の型付けに Zod がよく使われます。エージェントに自走させるなら、出力を機械的に検証して「形が違えばやり直す」ループを組めるのが強みです。

WARNING

Zod は「形(スキーマ)」を検証しますが、内容の正しさまでは保証しません。LLM が形は合っているが中身が間違った JSON を返すことはあります。スキーマ検証は「最低限の門番」であって、事実確認や業務ルールの検証は別途必要です。「parse が通った=正しい」ではない点に注意してください。

まとめ

  • Zod はスキーマ1つで実行時検証と TypeScript 型を兼ねる。型では守れない「外から来るデータ」の門番
  • Zod 4 は Zod 3 比で大幅高速化(文字列約14.71倍など)+コアバンドル57%削減
  • 文字列フォーマットは z.email() などトップレベルへ、エラー指定は error に統一
  • メタデータは .meta() と registry で管理、z.toJSONSchema() で JSON Schema へ変換できる
  • 極小バンドル狙いには関数型の Zod Minizod/mini
  • 使いどころはフォーム・API 境界・環境変数、そしてLLM の構造化出力検証。ただし「形」の検証であって「内容の正しさ」は別

TypeScript の型が「自分のコードの中」を守るなら、Zod は「世界との境界」を守ります。Zod 4 はその境界の防御を、より速く・軽く・LLM 時代向けに整えた版です。

参考リンク