Zodスキーマ vs TypeScriptインターフェース:それぞれの使い分け

ZodランタイムバリデーションスキーマとTypeScriptコンパイル時インターフェースを比較。それぞれの使い分けと、最大限の型安全性を得るための組み合わせ方を学びます。

Advanced

詳細な説明

ランタイム vs コンパイル時の型安全性

TypeScriptインターフェースとZodスキーマは異なる目的を果たします。それぞれをいつ使うか、そしてどう組み合わせるかを理解することが、堅牢なアプリケーション構築の鍵です。

TypeScriptインターフェース(コンパイル時のみ)

interface User {
  id: number;
  name: string;
  email: string;
}

// TypeScriptはコンパイル時にあなたを信頼します
const user: User = JSON.parse(apiResponse);
// ランタイムバリデーションなし!APIが不正なデータを返してもTypeScriptは検出しません。

Zodスキーマ(ランタイム + コンパイル時)

import { z } from "zod";

const userSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
});

type User = z.infer<typeof userSchema>;

// ランタイムバリデーションが不正なデータをキャッチ
const user = userSchema.parse(JSON.parse(apiResponse));
// データが一致しない場合ZodErrorをスロー

比較

特徴 TypeScriptインターフェース Zodスキーマ
コンパイル時の型 はい はい(z.infer経由)
ランタイムバリデーション なし あり
カスタムバリデーション なし あり(.email()、.min()、.refine())
デフォルト値 なし あり(.default())
データ変換 なし あり(.transform())
エラーメッセージ コンパイルエラーのみ 詳細なランタイムエラー
バンドルサイズ影響 なし(消去される) ~13KB(minified + gzipped)
学習曲線 低い 中程度

TypeScriptのみを使うべき場合

  • 内部データ — 信頼境界を越えない状態(コンポーネントprops、関数の戻り値)。
  • パフォーマンスクリティカルなホットパス — ~1msのパースオーバーヘッドが重要な場合。
  • シンプルなアプリケーション — すべてのデータソースを完全に信頼できる場合。

Zodを使うべき場合

  • API境界 — 外部APIからのレスポンスの検証。
  • ユーザー入力 — フォームデータ、クエリパラメータ、ファイルアップロード。
  • 環境変数 — 起動時の設定パース。
  • データベース結果 — ORM出力が期待に一致することの確認。
  • Webhookペイロード — 外部システムのコールバック。

ベストプラクティス:両方を組み合わせる

// スキーマを一度定義し、そこから型を派生
const userSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
});

// 型は派生される — 重複なし
type User = z.infer<typeof userSchema>;

// 内部コードには型を使用
function formatUser(user: User): string {
  return \`\${user.name} <\${user.email}>\`;
}

// 信頼境界ではスキーマを使用
async function fetchUser(id: number): Promise<User> {
  const res = await fetch(\`/api/users/\${id}\`);
  return userSchema.parse(await res.json());
}

このパターンにより、内部コードではゼロオーバーヘッドの型チェック、境界ではランタイムの安全性という両方の利点が得られます。

ユースケース

TypeScriptプロジェクトにZodを追加するかどうかを評価し、コンパイル時のみの型とランタイムバリデーションスキーマのトレードオフを理解する必要がある場合に使用します。

試してみる — JSON to Zod Schema

フルツールを開く