Ahmed Mahmoud

Headline: Zod 4 は TypeScript 優先のスキーマバリデーションライブラリの書き直し版で、2025 年に安定版のメジャーバージョンとしてリリースされました。私のコードに直接影響した変更は 4 つあります。文字列フォーマットがトップレベルの関数になりました(z.string().email() ではなく z.email())、4 つのエラーオプションが 1 つの error パラメータに統合され、エラー整形はスタンドアロンのヘルパー関数(z.flattenErrorz.treeifyErrorz.prettifyError)に移行し、.strict()/.passthrough()z.strictObject()/z.looseObject() になりました。非推奨となった Zod 3 の API は警告付きで引き続き動作するため、段階的に移行できました。

重要なポイント

  • Zod 4 は TypeScript 優先のスキーマバリデータとして 2025 年にリリースされた安定版のメジャーバージョンです。TypeScript 5.5 以降が必要です。
  • 文字列フォーマットはツリーシェイカブルなトップレベルの関数になりました — z.email()z.uuid()z.url() — そして z.string().email() は非推奨ですが、引き続き動作します。
  • 1 つの error パラメータが、Zod 3 の messageinvalid_type_errorrequired_error、および errorMap に置き換わりました。
  • エラー整形は z.flattenError(フォームフィールド用)、z.treeifyError(ネスト構造用)、z.prettifyError(人間が読みやすい文字列用)のヘルパー関数に移行しました。
  • zod/mini ビルドは、関数型でツリーシェイカブルな API を通じて同じバリデータを提供します。z.infer.parse().safeParse() は変更されていません。

私はほぼすべてのプロジェクトで Zod を使用し、リクエストボディ、フォームデータ、環境変数、API レスポンスなどの信頼できない入力を境界で検証しています。Zod 4 は表面上の API がかなり変更されたため、機械的なアップグレードでいくつかのファイルに影響が出たため、何が変更されたのかを正確に整理しました。

Zod 4 で実際に何が変わったのか?

Zod 4 は TypeScript 優先のスキーマバリデーションライブラリの完全な書き直し版で、2025 年に安定版のメジャーバージョンとしてリリースされました。目玉はパフォーマンスです。Zod チームのリリースノートによると、TypeScript コンパイラのインスタンス化が大幅に削減され、実行時の解析も高速化されており、スキーマの型が型チェック時間を支配する大規模なコードベースで特に重要です。私のコードに直接影響した API の変更は 4 つあります。文字列フォーマットがトップレベルの関数に移動したこと、エラーオプションが 4 つから 1 つに統合されたこと、エラー整形がスタンドアロンのヘルパー関数に移動したこと、そして .strict()/.passthrough()z.strictObject()/z.looseObject() になったことです。

なぜ z.string().email() が z.email() になったのか?

Zod 4 では文字列フォーマットをスタンドアロンのトップレベル関数 — z.email()z.uuid()z.url()、および z.iso 配下の ISO ヘルパー — として提供するようになりました。チェーン形式は引き続き動作しますが、非推奨となり警告が出ます。理由はツリーシェイキングのためです。各フォーマットが独立した関数になったことで、メールのみを検証するバンドルでは他のフォーマットのロジックを含める必要がなくなりました。

import * as z from "zod";

const User = z.object({
  id: z.uuid(),
  email: z.email(),
  website: z.url().optional(),
  age: z.number().int().min(18),
});

type User = z.infer<typeof User>;

Enter fullscreen mode Exit fullscreen mode

Zod 4 でカスタムエラーメッセージを設定するには?

Zod 4 では 4 つの個別のエラーオプションを 1 つの error パラメータに置き換えました。Zod 3 では messageinvalid_type_errorrequired_error、または完全な errorMap を渡していましたが、Zod 4 では 1 つの error を渡します。これは固定メッセージの場合は文字列、または issue を受け取ってメッセージを返す関数のいずれかで、1 箇所で欠損値と型違いを区別できます。

// Zod 4: one error param — string or function
z.string({ error: "Name is required" });

z.string({
  error: (issue) =>
    issue.input === undefined ? "Name is required" : "Name must be text",
});

Enter fullscreen mode Exit fullscreen mode

ZodError をフォームエラーに変換するには?

Zod 4 ではエラー整形を 3 つのトップレベルヘルパー関数に移動しました。z.flattenError(error){ formErrors, fieldErrors } を返し、フォームのフィールドレベルメッセージにマッピングできます。z.treeifyError(error) はスキーマの形状を反映したネストオブジェクトを返します。z.prettifyError(error) はログ用の人間が読みやすい複数行文字列を返します。生の error.issues 配列は変更されておらず、error.format()error.flatten() はこれらのヘルパー関数に置き換えられ非推奨となりました。

const result = User.safeParse(await request.json());

if (!result.success) {
  const { fieldErrors } = z.flattenError(result.error);
  return Response.json({ errors: fieldErrors }, { status: 400 });
}

const user = result.data; // fully typed as User

Enter fullscreen mode Exit fullscreen mode

zod/mini を使用するタイミングは?

バンドルサイズが重要になる場合 — クライアントコード、エッジ関数、出荷するウィジェット — に zod/mini を使用し、それ以外の場合は zod パッケージ全体を使用します。zod/mini は関数型 API を通じて同じバリデータを提供します。.optional() をチェーンする代わりに z.optional() でラップし、refinements は .refine() ではなく .check() を使用します。より冗長ですが、メソッドチェーンがないため、未使用のコードがツリーシェイキングで削除されます。両方のビルドは同じコアを共有しているため、実行時の動作は同一です。

import * as z from "zod/mini";

const User = z.object({
  email: z.email(),
  name: z.optional(z.string()),
});

Enter fullscreen mode Exit fullscreen mode

懸念事項 zod (フル) zod/mini
API スタイル チェーンメソッド(.optional() 関数ラッパー(z.optional()
バンドルサイズ 大きい 小さい、ツリーシェイカブル
使いやすさ 流暢で読みやすい より冗長
同じバリデータ はい はい(同じコア)
最適な用途 サーバー、一般的なコード エッジ/クライアント、サイズが重要なバンドル

Zod 3 から移行してすべてを壊さないようにするには?

段階的に移行してください。Zod 4 は非推奨の Zod 3 API を削除するのではなく、警告付きで動作し続けます。移行期間中、Zod は新しいバージョンを zod/v4 インポートパス([email protected] 内)で公開したため、[email protected] の前にファイルごとに採用できました。レガシー API は zod/v3 で引き続き利用可能です。私の手順は次の通りです。パッケージをアップグレードし、型チェッカーとテストを実行し、非推奨警告を段階的に解消します — 文字列フォーマットの呼び出しをリネームし、エラーオプションを error に統合し、.strict()/.passthrough() を新しいオブジェクト関数に切り替えます。z.infer.parse().safeParse() は変更されていないため、ほとんどのスキーマは変更せずに動作し続けました。

FAQ

Q: Zod 4 で z.string().email() は削除されましたか?
A: いいえ。引き続き動作しますが、非推奨で警告が出ます。推奨形式はトップレベルの z.email() で、両方とも同一の検証を行います。

Q: Zod 4 で errorMap と invalid_type_error の代わりは何になりましたか?
A: 1 つの error パラメータ — 固定メッセージの場合は文字列、条件付きメッセージの場合は issue を受け取る関数です。

Q: Zod 4 でフォーム用のフィールドレベルエラーを取得するには?
A: z.flattenError(error) を呼び出します。返される fieldErrors は各スキーマキーをそのメッセージにマッピングします。ネストされた形状には z.treeifyError を使用します。

Q: zod/mini は別のライブラリですか?
A: いいえ。Zod 4 のビルドで、同じバリデータをツリーシェイカブルな関数型 API で提供するものです。

Q: Zod 4 には特定の TypeScript バージョンが必要ですか?
A: はい。Zod 4 には TypeScript 5.5 以降が必要です。


Originally published on devya.dev. Also on eng-ahmed.com. Built by Devya Solutions.