💎 Zod 4 is now stable!  Read the announcement.
Zod logo

メタデータとレジストリ (Metadata and registries)

ドキュメント、コード生成、AI 構造化出力、フォーム検証、その他の目的のために、スキーマをいくつかの追加の メタデータ に関連付けると便利なことがよくあります。

レジストリ (Registries)

Zod でのメタデータは レジストリ を介して処理されます。レジストリはスキーマのコレクションであり、それぞれが 強く型付けされた メタデータに関連付けられています。単純なレジストリを作成するには:

import * as z from "zod";
 
const myRegistry = z.registry<{ description: string }>();

このレジストリにスキーマを登録、検索、削除するには:

const mySchema = z.string();
 
myRegistry.add(mySchema, { description: "A cool schema!"});
myRegistry.has(mySchema); // => true
myRegistry.get(mySchema); // => { description: "A cool schema!" }
myRegistry.remove(mySchema);
myRegistry.clear(); // wipe registry

TypeScript は、各スキーマのメタデータがレジストリの メタデータタイプ と一致することを強制します。

myRegistry.add(mySchema, { description: "A cool schema!" }); // ✅
myRegistry.add(mySchema, { description: 123 }); // ❌

id の特別な処理 — Zod レジストリは id プロパティを特別に扱います。同じ id 値で複数のスキーマが登録されている場合、Error がスローされます。これは、グローバルレジストリを含むすべてのレジストリに当てはまります。

.register()

注意 — このメソッドは、新しいスキーマを返さないという点で特別です。代わりに元のスキーマを返します。他の Zod メソッドはこれをしません!これには、新しいインスタンスを返す .meta().describe() (以下に記載)が含まれます。

スキーマは、レジストリにより便利に追加するための .register() メソッドを提供します。

const mySchema = z.string();
 
mySchema.register(myRegistry, { description: "A cool schema!" });
// => mySchema

これにより、スキーマ内でメタデータを「インライン」で定義できます。

const mySchema = z.object({
  name: z.string().register(myRegistry, { description: "The user's name" }),
  age: z.number().register(myRegistry, { description: "The user's age" }),
})

メタデータタイプなしでレジストリが定義されている場合、メタデータなしで汎用的な「コレクション」として使用できます。

const myRegistry = z.registry();
 
myRegistry.add(z.string());
myRegistry.add(z.number());

メタデータ (Metadata)

z.globalRegistry

便宜上、Zod は JSON Schema 生成やその他の目的でメタデータを保存するために使用できるグローバルレジストリ (z.globalRegistry) を提供します。次のメタデータを受け入れます。

export interface GlobalMeta {
  id?: string ;
  title?: string ;
  description?: string;
  deprecated?: boolean;
  [k: string]: unknown;
}

スキーマのメタデータを z.globalRegistry に登録するには:

import * as z from "zod";
 
const emailSchema = z.email().register(z.globalRegistry, { 
  id: "email_address",
  title: "Email address",
  description: "Your email address",
  examples: ["[email protected]"]
});

GlobalMeta インターフェースをグローバルに拡張するには、宣言のマージ を使用します。コードベースの任意の場所に以下を追加します。プロジェクトのルートに zod.d.ts ファイルを作成するのが一般的な規則です。

declare module "zod" {
  interface GlobalMeta {
    // add new fields here
    examples?: unknown[];
  }
}
 
// forces TypeScript to consider the file a module
export {}

.meta()

より便利なアプローチとして、.meta() メソッドを使用してスキーマを z.globalRegistry に登録します。

const emailSchema = z.email().meta({ 
  id: "email_address",
  title: "Email address",
  description: "Please enter a valid email address",
});

引数なしで .meta() を呼び出すと、スキーマのメタデータを 取得 します。

emailSchema.meta();
// => { id: "email_address", title: "Email address", ... }

メタデータは 特定のスキーマインスタンス に関連付けられています。Zod メソッドは不変であり、常に新しいインスタンスを返すため、これを念頭に置くことが重要です。

const A = z.string().meta({ description: "A cool string" });
A.meta(); // => { description: "A cool string" }
 
const B = A.refine(_ => true);
B.meta(); // => undefined

.describe()

.describe() メソッドは Zod 3 との互換性のためにまだ存在しますが、現在は .meta() が推奨されるアプローチです。

.describe() メソッドは、description フィールドのみを使用してスキーマを z.globalRegistry に登録するためのショートハンドです。

const emailSchema = z.email();
emailSchema.describe("An email address");
 
// equivalent to
emailSchema.meta({ description: "An email address" });

カスタムレジストリ (Custom registries)

カスタムレジストリの簡単な例はすでに見てきました。

import * as z from "zod";
 
const myRegistry = z.registry<{ description: string };>();

いくつかの上級パターンを見てみましょう。

推論された型の参照 (Referencing inferred types)

メタデータ型がスキーマの 推論された型 を参照することは、しばしば価値があります。たとえば、examples フィールドにスキーマの出力の例を含めたい場合があります。

import * as z from "zod";
 
type MyMeta = { examples: z.$output[] };
const myRegistry = z.registry<MyMeta>();
 
myRegistry.add(z.string(), { examples: ["hello", "world"] });
myRegistry.add(z.number(), { examples: [1, 2, 3] });

特別なシンボル z.$output は、スキーマの推論された出力タイプ (z.infer<typeof schema>) への参照です。同様に、z.$input を使用して入力タイプを参照できます。

スキーマタイプの制約 (Constraining schema types)

z.registry() に2番目のジェネリックを渡して、レジストリに追加できるスキーマタイプを制約します。このレジストリは文字列スキーマのみを受け入れます。

import * as z from "zod";
 
const myRegistry = z.registry<{ description: string }, z.ZodString>();
 
myRegistry.add(z.string(), { description: "A number" }); // ✅
myRegistry.add(z.number(), { description: "A number" }); // ❌ 
//             ^ 'ZodNumber' is not assignable to parameter of type 'ZodString' 

On this page