💎

Zod v4のβ版が公開されたぞ!注目すべき変更点

2025/04/11に公開

はじめに

お疲れさまです!あつあつのご飯にスクランブルエッグを乗せました。Meloです。

Zodは、TypeScriptで人気の高いスキーマ定義+バリデーションライブラリです。このたびv4のベータ版が公開され、いくつかの注目すべき変更が加えられました。この記事では、特に私が興味深いと思った変更点をピックアップして紹介します。

なお、現在はベータ版のため、以下のコマンドでインストールできます:

Zod4
npm upgrade zod@next

1. 文字列バリデーション関数のトップレベル化

これまでメソッドチェーンで記述していた文字列バリデーション(z.string().email()など)が、v4ではトップレベルの関数として提供されるようになりました:

// Zod v3
const emailSchema = z.string().email();
const urlSchema = z.string().url();

// Zod v4
const emailSchema = z.email();
const urlSchema = z.url();

The method forms (z.string().email()) still exist and work as before, but are now deprecated.
(z.string().email()メソッドは存続し以前と同様に機能するが、現在は非推奨)

ということで、将来的には削除されるかもしれません。

また、IPアドレスのバリデーションについても変更があります:

// Zod v3
const ipSchema = z.string().ip();

// Zod v4
const ipv4Schema = z.string().ipv4();
const ipv6Schema = z.string().ipv6();
// 両方のバージョンに対応する場合
const ipSchema = z.union([ipv4Schema, ipv6Schema]);

z.string().ip()は削除され、より明示的な.ipv4().ipv6()メソッドが別々に提供されるようになりました。両方のバージョンに対応する必要がある場合は、z.union()を使用して組み合わせます。

2. エラーカスタマイズの統一

カスタマイズエラーメッセージの設定方法が統一され、より一貫性のある方法で定義できるようになりました:

// Zod v3
z.string().min(5, { message: "5文字以上で入力してください" });
z.string({ 
  required_error: "このフィールドは必須です",
  invalid_type_error: "文字列を入力してください", 
});

// Zod v4
z.string().min(5, { error: "5文字以上で入力してください" });
z.string({ 
  error: (issue) => issue.input === undefined 
    ? "このフィールドは必須です" 
    : "文字列を入力してください" 
});

これまでのmessageinvalid_type_errorrequired_errorなどの複数のエラーカスタマイズパラメータが、単一のerrorパラメータに統一されました。
messageパラメータは当面の間はサポートされますが、将来的に削除される可能性があるため、新しいerrorパラメータへの移行が推奨されています。

3. エラーハンドリングの刷新

エラーハンドリングの仕組みが大きく変更されました。最も重要な変更点として、ZodErrorクラスがJavaScript標準のErrorクラスを継承しなくなりました:

// Zod v3
try {
  z.string().parse(data)
} catch(err) {
  if (err instanceof Error) {
    // エラー処理
  }
}

// Zod v4
try {
  z.string().parse(data)
} catch(err) {
  if (err instanceof z.ZodError) {
    // ZodErrorの処理
  } else if (err instanceof Error) {
    // 通常のError処理
  }
}

v4ではinstanceof Errorチェックがfalseを返すようになったため、既存のエラーハンドリングコードがある場合は、上記のような形でZodErrorの判定を先に行うように修正することをお勧めします。

パフォーマンスの改善

JavaScriptのErrorインスタンスの生成時には、コールスタックのスナップショットを取得する必要があり、このプロセスに時間がかかっていました。Errorクラスの継承をやめることで、エラーハンドリング時のパフォーマンスが大幅に向上しています。

4. オブジェクト操作の改善

まず前提として、Zodでのオブジェクトのバリデーションには、主に次のような方法があります:

  1. 厳密なバリデーション(strict)

    • スキーマで定義されていないプロパティが存在する場合にエラーを出す
    // Zod v3
    const schema = z.object({
      name: z.string()
    }).strict();
    
    schema.parse({ name: "Melo" }); // ✅
    
    schema.parse({ name: "Melo", age: 25 }); // ❌ エラー: ageはスキーマに定義されていない
    
    • 用途:APIのリクエスト/レスポンスなど、厳密なデータ構造が必要な場合
  2. 緩いバリデーション(passthrough)

    • スキーマで定義されていないプロパティも許可し、そのまま通す
    // Zod v3
    const schema = z.object({
      name: z.string()
    }).passthrough();
    
    const result = schema.parse({ name: "Melo", age: 25 }); // ✅(ageも結果に含まれる)
    // result = { name: "Melo", age: 25 }
    
    • 用途:フォームデータなど、追加のプロパティを許容したい場合

v4では、これらのメソッドチェーン方式が非推奨となり、専用の関数が導入されました:

// Zod v3
const strictObj = z.object({name: z.string()}).strict();
const looseObj = z.object({name: z.string()}).passthrough();

// Zod v4
const strictObj = z.strictObject({name: z.string()});
const looseObj = z.looseObject({name: z.string()});

また、新しくz.interface()が導入され、より直感的なオブジェクト定義が可能になりました:

// z.interface()を使用したスキーマ定義
const User = z.interface({
  name: z.string(),
  "age?": z.number(), // オプショナルフィールド
});

// 必須フィールドのみで検証OK
User.parse({ name: "Melo" }); // ✅

// オプショナルフィールドを含めても検証OK
User.parse({ name: "Melo", age: 25 }); // ✅

// 必須フィールドが欠けているとエラー
User.parse({ age: 25 }); // ❌ エラー: nameは必須です

この新たなz.interface()構文により、TypeScriptのインターフェース定義に近い直感的な方法でスキーマを定義できるようになりました。特にオプショナルフィールドの定義が"age?"のように明示的に行えるようになり、コードの意図がより明確になります。

5. その他新機能の追加

ここでの紹介は割愛しますが、他にも以下のような機能が追加されました(一部):

  1. JSONスキーマ変換のネイティブサポート
  2. メタデータと登録機能
  3. エラーのプリティプリント機能

6. パフォーマンスの大幅な向上

v4では、実測値に基づく劇的なパフォーマンス改善が実現されています:

処理速度の向上

  1. 文字列処理: 2.63倍高速化
  2. 配列処理: 3倍高速化
  3. オブジェクト処理: 7倍高速化

バンドルサイズの最適化

  • コアライブラリ: 30%削減

    • Zod v3: 12.47kb (gzip)
    • Zod v4: 8.77kb (gzip)
  • 新パッケージ @zod/mini: 超軽量版

    • バンドルサイズ: 2.23kb (gzip)
    • Zod v3比: 約5.7倍の削減

これらの改善により、大規模なアプリケーションでのバリデーション処理が大幅に効率化され、より快適な開発体験が実現されています。特に@zod/miniの導入により、バンドルサイズを重視するプロジェクトでも気軽にZodを採用できるようになりました。

まとめ

Zod v4は、文字列バリデーションの簡潔な記法やエラーハンドリングの統一、パフォーマンスの大幅な向上など、日々の開発体験を快適にしてくれる変更が多いなと感じました。

一方で、しかし今回紹介した項目以外にも非推奨や削除されるものも多くあり、移行には注意が必要です。

弊社では一緒に働く仲間を募集しています!

株式会社コードユニットは 「エンジニアが自由に挑戦し、成長できる環境を創る」 をビジョンに掲げるIT企業です。
モダンな技術スタックを使った開発や、このような技術的課題に日々チャレンジできる環境で、楽しく開発をしています。
そんな弊社では以下のような方を募集しています:

  • 新しい技術に挑戦したい方
  • 現状に満足せず、常にスキルアップを目指せる方
  • 知らない情報にアンテナを張っている方
  • ビジョンに共感し、会社と共に成長してくれる方

興味を持っていただけた方は、ホームページからご連絡ください。カジュアル面談も実施していますので、お気軽にお問い合わせください!

参考リンク

株式会社コードユニット

Discussion