1 ポイント 投稿者 GN⁺ 2025-05-20 | 1件のコメント | WhatsAppで共有
  • Zod 4が1年間の開発を経て安定版として公開され、Zod 3の設計上の限界を修正し、性能・バンドルサイズ・TypeScriptコンパイル効率を大幅に改善
  • 2021年5月に登場したZod 3は、GitHubスター2,700・週間ダウンロード60万から、現在は37.8kスター週間3,100万ダウンロード規模へ成長し、24個のマイナーバージョンを経て主要な改善には破壊的変更が必要に
  • ベンチマークでは文字列パースが14倍、配列パースが7倍、オブジェクトパースが6.5倍高速化し、tscの型インスタンス化も簡単な例で25,000回超から約175回へ減少
  • コアバンドルサイズはgzip基準でZod 3の12.47kbからZod 4通常版の5.36kbへ縮小し、ツリーシェイキング可能な関数型APIであるZod Mini1.88kbまで小型化
  • 新機能にはJSON Schema変換、メタデータレジストリ、再帰オブジェクト型推論、国際化、エラーのpretty-printing、テンプレートリテラル型、z.stringbool()、統合されたerrorパラメータ、改善されたz.discriminatedUnion()などが含まれる

Zod 4が新しいメジャーバージョンになった理由

  • Zod 4は1年間の活発な開発を経て安定版となり、より高速で小さく、tsc効率の高い基盤の上に、長らく要望されていた機能を実装
  • Zod v3.0は2021年5月にリリースされ、当時のGitHubスターは2,700、週間ダウンロードは60万だった
  • 現在ZodはGitHubスター37.8k、週間ダウンロード3,100万を記録
    • ベータ版が出た6週間前は、週間ダウンロードが2,300万だった
  • 24個のマイナーバージョンが積み重なる中でZod 3のコードベースは限界に達し、最も要望の多かった機能と改善には破壊的変更が必要だった
  • Zod 4は最も多くの推薦を受けた公開Issue 10件のうち9件をクローズ

パース性能とTypeScriptコンパイル効率

  • Zod 4はリポジトリで直接実行できるベンチマークを提供
  • パース性能の改善:
    • 文字列パース: 14倍高速化
    • 配列パース: 7倍高速化
    • オブジェクトパース: 6.5倍高速化
  • オブジェクトパースのベンチマークではMoltar validation library benchmarkを実行
  • tsc --extendedDiagnostics基準の簡単なファイルのコンパイルで、型インスタンス化が大幅に減少
    • "zod/v3"使用時は25,000回超
    • "zod/v4"使用時は約175回
  • Zod 4はZodObjectと他のスキーマクラスのジェネリクスを再設計・単純化し、インスタンス化の急増を回避
  • .extend().omit()を繰り返し連結するパターンは、Zod 3ではコンパイルに4000msかかり、追加の.extend()呼び出しで"Possibly infinite"エラーを引き起こす可能性があった
  • 同じパターンがZod 4では400msでコンパイルされ、10倍高速化
  • 今後tsgoコンパイラと併用すれば、Zod 4のエディタ性能はより大きなスキーマやコードベースまでスケールできる可能性がある

バンドルサイズとZod Mini

  • 単純なz.boolean()検証スクリプトをrollupでバンドルし、コアバンドルサイズを比較
  • gzip基準のコアバンドルサイズ:
    • Zod 3: 12.47kb
    • Zod 4通常版: 5.36kb
  • Zod 4通常版のコアバンドルはZod 3より約57%小さく、2.3倍削減
  • Zodのメソッド中心APIは根本的にツリーシェイキングが難しく、単純なz.boolean()スクリプトでも.optional().array()のような未使用メソッドの実装を一緒に取り込む
  • Zod Minizodと1:1で対応する、関数型でツリーシェイキング可能なAPIを提供
    • Zodがメソッドを使う箇所で、Zod Miniは通常ラッパー関数を使用
    • パースメソッドはZodとZod Miniで同一
    • 汎用.check()メソッドでrefinementを追加
  • 通常のZodは大半のユースケースで引き続き推奨され、例外的に厳しいバンドルサイズ制約があるプロジェクトではZod Miniを検討できる
  • zod/mini使用時のgzipバンドルサイズは1.88kb
    • Zod 3比で85%、6.6倍削減
    • 比較表: Zod 3 12.47kb、Zod 4通常版 5.36kb、Zod 4 Mini 1.88kb
  • 詳細はzod/miniドキュメントで確認できる

メタデータとJSON Schema

  • Zod 4はスキーマに強く型付けされたメタデータを追加する新しいシステムを導入
  • メタデータはスキーマ自体ではなく、スキーマとtyped metadataを結び付けるschema registryに保存される
  • z.registry()でレジストリを作成でき、スキーマの.register()メソッドによる便利な登録も可能
  • Zodは共通のJSON Schema互換メタデータを受け取るグローバルレジストリz.globalRegistryをエクスポート
  • .meta()メソッドはスキーマをz.globalRegistryへ手軽に追加する
  • Zod 3との互換性のため.describe()は引き続き提供されるが、Zod 4では.meta()が推奨される
  • Zod 4はz.toJSONSchema()によるファーストパーティのJSON Schema変換を提供
  • z.globalRegistryのメタデータはJSON Schema出力に自動的に含まれる
  • 生成されるJSON Schemaのカスタマイズ情報はJSON Schema docsにある

新しいスキーマ表現と型機能

  • Zod 4は再帰オブジェクト型を適切に推論できる
    • 再帰型と相互再帰型を表現できる
    • Zod 3の再帰型パターンと異なり、型キャストが不要
    • 結果のスキーマは通常のZodObjectインスタンスであり、すべてのメソッドを使用できる
  • Fileインスタンス検証用のFile schemaが追加
  • z.templateLiteral()はTypeScriptのテンプレートリテラル型を表現
    • 文字列化可能なZodスキーマ型は内部正規表現を保存
    • 対象には文字列、z.email()のような文字列フォーマット、数値、boolean、bigint、enum、literal、undefined/optional、null/nullable、別のtemplate literalが含まれる
    • z.templateLiteralコンストラクタはこれらを1つのsuper-regexにつなぎ合わせる
    • z.email()のような文字列フォーマットは正しく強制されるが、custom refinementは強制されない
    • 詳細はtemplate literal docsにある
  • 固定幅整数と浮動小数点型を表現する新しい数値フォーマットが追加
    • 適切なinclusive minimum/maximum制約がすでに追加されたZodNumberインスタンスを返す
  • JavaScriptのnumberで安全に表現できる範囲を超えるbigint数値フォーマットも追加
    • 適切なinclusive minimum/maximum制約がすでに追加されたZodBigIntインスタンスを返す
  • z.literal()は複数の値を選択的に受け取れるようになった

エラー、国際化、文字列フォーマット

  • Zod 4はエラーメッセージを複数言語へグローバルに翻訳する新しい**locales API**を導入
  • 対応ロケールの完全な一覧はCustomizing errorsにあり、対応言語が追加されるたびに更新される
  • ZodはZodErrorをユーザーフレンドリーな形式の文字列へ変換するトップレベル関数z.prettifyErrorを実装
    • 現在のフォーマットは設定できない
    • 今後変更される可能性がある
    • 既存のzod-validation-errorを使用中なら引き続き利用できる
  • emailなどすべての文字列フォーマットはzモジュールのトップレベル関数へ昇格
    • より簡潔でツリーシェイキングに有利
    • z.string().email()のようなメソッド対応APIは引き続き利用できるがdeprecated状態
    • 次のmajorバージョンで削除予定
  • z.email() APIはcustom regular expressionをサポート
    • canonical email regexは1つに定まっておらず、アプリケーションごとにより厳格または緩い基準を選べる
    • Zodは利便性のため、一般的な正規表現をいくつかエクスポート

boolean変換とエラーカスタマイズの単純化

  • 既存のz.coerce.boolean()はfalsy値をfalse、truthy値をtrueに変換する単純なAPI
    • falseundefinednull0""NaNなどはfalseになる
    • この動作は他のz.coerce APIと一致
  • Zod 4はenv風のより精巧なboolean coercionのために**z.stringbool()**を導入
  • Zod 4の破壊的変更の大半はエラーカスタマイズAPIに関するもの
  • エラーカスタマイズは単一のerrorパラメータへ統合
    • messageerrorに置き換えられる
    • messageパラメータは引き続きサポートされるがdeprecated状態
    • invalid_type_errorrequired_errorは関数構文のerrorに置き換えられる
    • errorMapも関数構文のerrorに置き換えられる

合成性、refinement、変換

  • z.discriminatedUnion()は従来サポートしていなかった複数のスキーマ型をサポート
    • unionとpipeが含まれる
    • discriminated unionを別のdiscriminated unionのメンバーとして使えるようになり、合成可能になった
  • Zod 3ではrefinementが元のスキーマをラップするZodEffectsクラスに保存されていた
    • この構造のため、.refine().min()のような他のスキーマメソッドと組み合わせて使いにくかった
  • Zod 4ではrefinementがスキーマ内部に保存され、.refine()と他のスキーマメソッドを自然に併用できる
  • 新しい.overwrite()メソッドはinferred typeを変えないtransformを表現
    • .transform()は出力型がランタイムでintrospectableではなく、transform関数が何でも返せるブラックボックス
    • そのためJSON Schemaへ安全に変換する方法がない
    • .overwrite()は元のクラスのインスタンスを返す
    • overwrite関数はrefinementとして保存され、inferred typeを変更しない
  • 既存の.trim().toLowerCase().toUpperCase().overwrite()を使って再実装

ライブラリ作者向けの基盤

  • Zod Miniの追加により、ZodとZod Miniが共有するコア機能を含むzod/v4/coreサブパッケージが作成された
  • zod/v4/coreはZodを単なるライブラリから、他のライブラリに組み込める高速な検証基盤へ拡張
  • スキーマライブラリを作る場合は、ZodとZod Miniの実装を参考にしてzod/v4/core上に構築できる
  • ライブラリ作者向けにFor library authorsガイドが提供される
    • Zod上に構築する際のbest practiceを扱う
    • Zod 3、Zod 4、Miniを同時にサポートする方法に関するよくある質問に答える

1件のコメント

 
GN⁺ 2025-05-20
Hacker News の意見
  • 作者です。何でも聞いてください。バージョン方針については、このアプローチの理由をかなり詳しくまとめてあります: https://github.com/colinhacks/zod/issues/4371
    結局のところ、npm は Zod が置かれた状況をうまく扱えるようには設計されていません。数十〜数百のライブラリが Zod のインターフェース/クラスを直接取り込み、自分たちの公開 API で使っているため、Zod がメジャーバージョンを上げるたびに、それらのライブラリも新しいメジャーバージョンを出さなければなりません
    単独で見れば合理的ですが、Zod では全員にとって苦痛なバージョンの雪崩が起きかねず、エコシステムのかなりの部分が v3 に永遠に固定されてしまいそうでした
    そこで Go の方式に似せて、パッケージが新しい破壊的変更を含むバージョンを出す代わりに、新しいサブパスを追加する方式を選びました。TypeScript エコシステムでは、ライブラリが zod@^3.25.0 だけを peer dependency として持ち、"zod/v3""zod/v4" から必要なものを取り込むことで、両方のバージョンを同時にサポートできます

    • 大規模なコードベースでの tsc の性能向上は特にうれしいですし、判別共用体の変更も、これまで不足していた特定のシナリオで大いに役立ちそうです
      ただ、特殊な事情のためにやや変わったバージョン方針を取った理由は理解できますが、推移的依存関係での Zod バージョン衝突を心配する必要がないチームの立場からすると、4.0.0 パッケージもあってほしかったです
      理解が正しければ import を "zod/v4" に変える必要がありますが、これはかなり騒がしい変更ですし、IDE が 'zod' から自動 import してしまう問題を lint ルールで捕まえなければならず、面倒になり得ます
    • この方式はとても合理的です。旧バージョンのセキュリティアップデートも同じコードベースのリリース内で一緒に提供できるという意味でもあります
    • モバイルなので記事にすでに書かれているか見られていませんが、TypeScript で .optional() を直す作業が上位 9〜10 件の issue 解決に含まれるのか気になります: https://github.com/colinhacks/zod/issues/635
      これが Zod で一番つらい点でしたが、それでも Zod がとても良いので我慢して使っています
    • 新機能のおかげで、ローカルで入れていた多くの暫定ハックをなくせそうです。フォーム名のタイプミスを避けるために https://github.com/raflymln/zod-key-parser の独自版を使っているのですが、こうした機能がライブラリ本体に直接入っていないのは意外でした
      これを Zod の範囲外と見ているのか、それともまだ実装する時間がなかっただけなのか気になります。関連する議論は https://github.com/colinhacks/zod/discussions/2134 にあります
    • Zod 4 の最も早いバージョンが 3.25.0 という意味なら、これはちょっと筋が通らないように聞こえます
      ここ数か月 Zod のアルファ版を使ってきて、単に package.json を直してアップグレードしたかったのですが、今では git 履歴全体を掘り返す必要がありそうです
      プロジェクトにはとても感謝していますが、このフィードバックに関しては必要以上に難しくしてしまったように思います。3.x と並行して 4.x も配布できたのではないでしょうか
  • 「移行を簡単にするため、Zod 4 を zod@3.25 リリースの一部として Zod 3 と一緒に配布し、"/v4" サブパスから取り込ませる」という内容は、npm の依存関係管理が完全にめちゃくちゃだというシグナルに見えます
    peer dependency があまりに壊れているため、v4 が v3 のふりをしなければならない状況になっています

    • 作者です。このアプローチの理由はここにかなり詳しく書いてあります: https://github.com/colinhacks/zod/issues/4371
      npm が Zod の置かれた状況をうまく管理できていないという点はその通りです。ただし Zod には、ほとんどどんなライブラリも受け入れないという制約があります。数十〜数百のライブラリが "zod" からインターフェース/クラスを直接取り込み、自分たちの公開 API で使っています
      こうしたライブラリは、Zod がメジャーバージョンを上げるたびに新しいメジャーバージョンを出す必要があり、Zod ではそれがバージョンの雪崩を引き起こして全員にとって苦痛になり得ます。正直、エコシステムのかなりの部分が v3 に永遠に固定されてしまいそうでした
      そこで Go に似せて、破壊的変更のあるリリースごとに新しいパッケージバージョンを出すのではなく、新しいサブパスを追加する方式を選びました。TypeScript エコシステムでは、zod@^3.25.0 という単一の peer dependency で "zod/v3""zod/v4" を同時にサポートできます
    • 「peer dependency が壊れているので v4 が v3 のふりをしている」という結論は正しくないように見えます。Zod v4 が v3 の中に含まれているのは、ユーザーが段階的に移行できるようにするためだと思います
      つまり、使用箇所を一つずつ import ... from 'zod/v4' にリファクタリングし、終わったら完全に v4 に上げる流れです
    • 否定的な言い方なら何でも支持されるような感じですね。この決定は npm 自体の本質的な限界というより、破壊的変更が多いライブラリを段階的に移行できるようにする実用的な方法に近いです
    • 何年も npm だけを使ってきたので視野が狭くなっているのかもしれませんが、v3 から v4 へ一度に大きく移るのではなく、反復的に移行するより良い方法が何なのか気になります
    • これは npm だけの問題ではありません。ある依存関係がさらに別の推移的依存関係で古いバージョンに依存している問題は、実質的にどのエコシステムでも起きます
      むしろ npm は、必要なら複数バージョンを同時に実行したり、推移的依存関係グラフの一部を選択的に上書きしたりできるので、逃げ道が多いほうです
      どのパッケージ管理システムがこの問題を解決しているのでしょうか? Maven のような「安定した」プラットフォームでも、Apache Commons が v2 から v3 に移るときのように、新しい名前空間でバージョンを出してこうした問題に対処しています
  • 以前から気になっていた疑問がある。Zod がこれに合うかもしれないと聞いたが、ドキュメントを見てもどうすればいいのかよく分からない。
    サーバー API が表現できるものよりも、より精巧な型を返すとしよう。たとえば api/:postid/author が User を返すが、通常の User の場合も匿名 User の場合もあり、usernamelocation のようなフィールドが null で来ることがある。この場合、User オブジェクトを判別ユニオンとして表現したくなるかもしれない。
    別のエンドポイントから来るオブジェクトも型変換が必要になることがある。User が時には Post[] を含み、Post がモデレーターの投稿なら特殊な属性を持つこともある。
    以前は normalizeUser()normalizePost() のような関数を書いていたが、すぐに散らかってしまった。エンドポイントごとに User/Post モデルの異なる部分集合を返すので、normalizePost を5個ほど作る羽目になり、かなり雑然としている。こういう問題は普通どう解くのか気になっている。

    • 判別ユニオンを使えばよさそう。
      status のような判別フィールドを基準に successfailed のオブジェクトを分けるような形。モデレーター用の特殊属性が多いが、全部列挙したり検査したりしたくないなら、パススルーの動作を定義できる。
      複数のメソッドが互いに異なるスキーマを持っていても共通部分があるなら、共有のオブジェクトスキーマを作り、そこに追加フィールドを載せたオブジェクトを作ればよい。可能性が多ければそれでも散らかるだろうが、すでに散らかっている状況なら、バリデーターは少なくともその散らかり具合を検証してくれる。
    • 理想的には、User がどんな形になり得るかについての単一の真実の情報源があるべき。これは User と AnonymousUser のような判別ユニオンかもしれない。
      フルスタック TypeScript でないなら、たとえば Python バックエンドでは複数の User 形態を Pydantic モデルとユニオンで定義し、OpenAPI/GraphQL スキーマ生成とコード生成を通じて TypeScript クライアント型を作れる。
    • ユースケースをもっと知らないと解決は難しいが、ユニオン内のすべての型に "user_type" のような判別プロパティを追加すると、通常ケースと特殊ケースを扱いやすくなる。
      たとえば user.user_type === 'authenticated' を検査すれば、型システムはその後に user.name を使えることを理解する。
    • 今回のケースに直接役立つわけではないが、こういうことのために GraphQL は作られた。
      GraphQL クエリ用の TypeScript ライブラリは、選択したフィールドの形からレスポンスの形を動的に推論できる。{ user { username posts { text } } } を選ぶと posts のあるレスポンス型になり、{ user { username } } だけを選ぶと posts プロパティは完全に消える。
    • サーバーが型を公開すべき。クライアント側で型を手書きするのは筋が通らない。
      サーバーは自分が送るデータを分かっているのだから、その情報をメタデータとしてクライアントに提供すべき。実務的には、Python バックエンドが Pydantic スキーマを使い、それを基に OpenAPI 仕様を自動生成し、クライアントが型を生成する、といった形になり得る。
  • Zod はこれまで見てきた代替手段よりはるかに良いが、こうした明示的な検証が必要だという事実そのものが、現代の Web 開発がどこに来てしまったのかを示す失敗のように感じることがある。
    フルスタック開発で同じ形を複数の方法で説明しなければならないのが、とてももどかしい。JS の入力検証、API 定義用の Swagger、サーバー側の入力検証、スキーマ適合性のための ORM、さらにサーバーとクライアントで別々の TypeScript 定義まで必要になって、うんざりする。

    • TypeScript が静的検査/コンパイル時専用のシステムにこだわっているのは、エコシステム全体にとって残念な傷跡だ。TypeScript にランタイム検査器になってほしいわけではないが、クラス・関数・オブジェクトについて有用に使える型データを出力してほしい。
      TypeScript は私たちが持つ最善の単一の真実の情報源のように感じられるが、実際にはリフレクションを試みるツールがそれぞれ自分のモデルとビルダーを再定義している。リフレクションが中核となる大きな領域だけで5つあり、それぞれに複数の実装がある。
      以前の TypeScript 型出力ツールである reflect-metadata はランタイム型情報を一部提供するが、非常に古いデコレーターとメタデータ仕様を対象としている: https://www.npmjs.com/package/reflect-metadata
      もしかすると統合の入り口に来ているのかもしれない。Standard Schema プロジェクトは主要な検証ライブラリの大半から支持されているようだ。ただし、これを API 定義や ORM ツールにまで広げるのはまだかなり初期段階。
      https://github.com/standard-schema/standard-schema?tab=readm...
    • 実のところ、これこそがこうしたツールの核心。1回だけ定義し、その下にあるすべてを動的に生成すればよい。
      Zod スキーマで一度変更すれば、型検査とともにアプリ全体へ伝播する。Zod スキーマが単一の真実の情報源になるわけだ。
    • 通常、データをあちこちで再定義する必要はない。Zod に変換したり Zod から変換したりするツールは非常に多い。
      すでに JSON Schema/Swagger スキーマがあるなら、そこから Zod を生成すればよい。TypeScript ORM を使っているなら、ほぼ間違いなく Zod ジェネレーターがあるはず。
      正直なところ、Zod はあまりに広く使われているので、自分にとってはスタック内の他のものが依存できる統合スキーマ定義になっている。型を直接定義するため、開発者が実際に最新状態を保つ。会社の Swagger ドキュメントは変更にいつも遅れる。
    • すべての API は実験的で、常に変化・進化している状態であり、Web も同じ。
      現状維持で問題ないのは、結果だけを求めて方法には関心のないクライアントや雇用主を相手にしている場合だけ。その文脈では、こうした不幸な複雑性の層も、少なくとも請求可能な時間を増やしてくれる。
    • 現代の Web 開発が複雑だと不満を言う人の多くは、これらすべてを単に TypeScript と Zod で置き換えようという提案にも嫌悪感を示しそうだ。
      もちろん、Zod が自分で選んだ TypeScript スキーマ定義および検証ライブラリである、という前提での話だ。
  • Zod 4 は良さそうだが、最新の改善を含めても ArkType は依然として一桁倍以上速い
    後方互換性と構文互換性のために、完全に新しく始めたライブラリほど大幅に速くするのが難しい場合がある。最近のプロジェクトでこれらのツールをすべて分析し、この理由もあって ArkType を選んだ。TypeScript の使用感もより良く感じた

    • 速度指標を見たが、その速さがどこで差を生むのか説明してもらえるか気になる
      私たちは Zod をフォーム検証にしか使っていないので、「なぜこれが重要なのか?」と思ってしまう。人々が高スループットな API 入力メッセージのようなものを検証していて、性能がより重要になるケースがあるのだろうかと思う
    • ArkType を TypeBox より選んだ理由が気になる
    • 興味深いことに、調査したときそのツールは見てもいなかった。私も特に TypeScript の使い心地を見ていた
      それでも Zod から乗り換えることはなさそう
    • ArkType は書くのが悪夢のようで、Zod は書きやすい
  • Zod チームの新リリースを祝福する。あまり否定的に聞こえるリスクを承知で言うと、マイグレーションガイドに書かれている 破壊的変更 の数を考えると身震いする
    Zod に大きく依存しているプロジェクトなら、開発者の集中力と時間をかなり必要とする大変な作業になりそうだ。職場で 4〜5 年もののフロントエンドプロジェクトをいくつか保守してきたので特に共感する
    大きな React プロジェクトはたいてい多くのライブラリに依存しており、それぞれのライブラリが大きな変更を出し、さらにドキュメントまで不足していると、あっという間に手に負えなくなる。JavaScript で仕事をするうえで最も嫌いな部分の一つで、すべてを合わせて滑らかに動き続けるようにする作業が、終わりのない上り坂のように感じられる

    • 完全に同意する。大きな Next.js アプリをいくつか運用しているが、この 1 年で Next.js 14 → 15 の大規模なキャッシュ変更、Next.js pages → app router、React 18 → 19、Eslint 8 → 9、Tailwind 3 → 4 を経験しなければならなかった
      正直、悪夢だったし、むしろ Django で作っていればよかったと思った。予想に反して、Tailwind 3 → 4 の移行は最も苦痛なものの一つだった
    • だから彼らは別の mini エディションとともに 二重提供方式 を選んだのだ。パッケージマネージャーをいじらずに段階的な移行をしやすい
      mini エディションに関心のないユーザーはその部分を気にする必要はない。ただし mini エディションのツリーシェイキング上の利点が非常に大きく、代替開発を刺激していたため、Zod はこれを受け入れるか衰退する必要があった
    • 単に LLM を使えばいい
  • 本番環境で数千人のユーザーを抱える SaaS を自分で運営しているフルスタック開発者として、SPA を作らず、JS フロントエンドフレームワークも使わないことにしたおかげで、自分がまったく知らずに済んでいる問題がどれほど多いかを、ときどき気持ちよく実感する
    Zod/ArkType のようなものが必要だと考えたことすらなく、初めて聞いたし、使うこともない
    SPA を作るのに必要な労力、複雑さ、ツールの多さには驚かされる。SPA を作らないと決めると、特定の問題群全体がそのまま存在しなくなる。その代わり、ブラウザを本来設計されたとおりに、ページ全体の再読み込みとバックエンド開発中心で使い、Laravel Livewire のようなバックエンド専用フレームワークで時々リアクティブ性を加える
    アクセス制御から検証、状態管理まで、すべてがシンプルだ。アプリは高速で、レスポンシブで、現代的で、SEO に強く、本番環境で数千人に提供されている

    • 5 つ以上のチームが一緒に働く 2 つの大きなプロジェクトで、Zod と Protobuf を使ってスキーマ進化がうまくいくようにした。軽量なフロントエンドであっても、バックエンドでスキーマを検証する何かを使うことには意味がある
      結局どこかにはスキーマがある。データベースシステムに定義されているかもしれないし、ORM モデルに定義されているかもしれない。しかし大きなプロジェクトでデータベースシステムや ORM にスキーマを置くと非常に難しい問題が生じ得るので、私たちは Zod と Protobuf を使っている。Protobuf も Zod か似たようなもので完全に置き換えられると思う
      英国 Post Office スキャンダルには Horizon という IT システムが関係している: https://en.wikipedia.org/wiki/British_Post_Office_scandal
      詳細を読んでみると、Zod のような スキーマ検証 があれば、このスキャンダルを防ぐ一助になったのではないかと思う。集団訴訟の裁判所文書の技術付録でも、スキーマ使用の欠如が言及されている: https://en.wikipedia.org/wiki/Bates_%26_Others_v_Post_Office...
    • Zod は SPA とは関係なく、フロントエンド専用ツールでもない。コードで入力検証をしていないのか?
    • 目を閉じれば、問題群全体が存在しなくなることもある
    • サーバー側の検証をどうしているのか気になる
      今の話だと、防御的に if 文を山ほど書いているように聞こえる。さらに悪い場合は、HTML クライアント側フォーム検証だけに依存しているのかもしれない
    • 私たちには、データパイプラインの一部として使っているバックエンド専用の Zod スキーマが非常にたくさんある。だから SPA の問題を解決するためだけに存在するツールには見えない
  • 専門家ではないので慎重に言いますが、JSON Schemaはスキーマベースなので、TypeScript 以外の言語でもバリデーターを実装でき、良い選択肢になり得ると思いました
    https://ajv.js.org はそのような JSON Schema ライブラリの一つです。Zod と比べてどうなのか気になります

    • Zod は JSON の検証だけのためのツールではありません。変換なしでは JSON で表現できないオブジェクト、たとえば日付やクラスインスタンスなどを検証できます
      望むなら JSON 変換器としても使えます。たとえば文字列を受け取り、ISO 日付文字列かどうかを検証して Date オブジェクトを出力するスキーマを作成できます
    • Zod 4 は Zod スキーマを JSON Schema に変換する機能をネイティブでサポートしています。以前もサードパーティーライブラリでは可能でした
      重要な違いは前処理と refine です。Zod では検証前にコールバックを提供でき、これは非常に有用ですが JSON では表現できません。たとえば日付検証の前に MM/DD/YYYYDD/MM/YYYY に変えることは、思ったより頻繁に役立ちます
    • そのような場合は JSON Schema が良い選択で、TypeBox はそれを生成するための手頃な方法です
      検証には AJV を使うか、TypeBox 自体のスキーマ検証システムを使えます。後者のほうがはるかに高速ですが同期式のみをサポートし、AJV にはデータベース確認のような非同期検証オプションがあります
    • 言語間の検証には JSON Schema が適しています。これを OpenAPI で包めば、ちゃんとした API ドキュメントも無料で得られます
  • この話題をめぐる否定的な反応には驚きました
    Zod v4 の初期バージョンをテストし、新しい API は気に入りましたが、移行パスがどうなるのか非常に心配していました。いっそ新しいパッケージ名で配布しようと提案することも考えていました
    しかし作者のアプローチは賢明です。すべての依存関係が更新されるのを待たなくても、私のような人が v4 をすぐ導入できるようにしてくれます

    • 良い道筋です。検証のようなものでは、全か無か式の移行を引き受ける方法はありません
  • 新しいプロジェクトに Zod を導入し始めたばかりでしたが、これ以上ないタイミングでした
    今見えている内容からすると、v4 に移るには本当に多くの変更が必要だっただろうと思います