Zod logo

元数据和注册表

将模式与一些额外的元数据关联起来通常是有用的,用于文档、代码生成、人工智能结构化输出、表单验证和其他用途。

🌐 It's often useful to associate a schema with some additional metadata for documentation, code generation, AI structured outputs, form validation, and other purposes.

注册表

🌐 Registries

Zod 中的元数据通过 注册表 来处理。注册表是模式的集合,每个模式都关联一些 强类型 元数据。要创建一个简单的注册表:

🌐 Metadata in Zod is handled via registries. Registries are collections of schemas, each associated with some strongly-typed metadata. To create a simple registry:

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

要在此注册表中注册、查找和删除模式:

🌐 To register, lookup, and remove schemas from this registry:

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 强制要求每个模式的元数据与注册表的元数据类型匹配。

🌐 TypeScript enforces that the metadata for each schema matches the registry's metadata type.

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

id 的特殊处理 — Zod 注册表对 id 属性有特殊处理。如果使用相同的 id 值注册多个模式,将会抛出 Error。这对所有注册表都适用,包括全局注册表。

.register()

注意 — 这个方法的特殊之处在于它不会返回一个新的模式;相反,它会返回原始模式。没有其他 Zod 方法会这样做!这包括 .meta().describe()(如下所述文档中)它们会返回一个新的实例。

模式提供了一个 .register() 方法,可以更方便地将其添加到注册表中。

🌐 Schemas provide a .register() method to more conveniently add it to a registry.

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

这让你可以在模式中“内联”定义元数据。

🌐 This lets you define metadata "inline" in your schemas.

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 提供了一个全局注册表(z.globalRegistry),可以用于存储 JSON 模式生成或其他用途的元数据。它接受以下元数据:

🌐 For convenience, Zod provides a global registry (z.globalRegistry) that can be used to store metadata for JSON Schema generation or other purposes. It accepts the following metadata:

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

要在 z.globalRegistry 中为一个模式注册一些元数据:

🌐 To register some metadata in z.globalRegistry for a schema:

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

要在全局增强 GlobalMeta 接口,请使用 声明合并。可以在代码库的任何位置添加以下内容。在项目根目录创建一个 zod.d.ts 文件是常见的约定。

🌐 To globally augment the GlobalMeta interface, use declaration merging. Add the following anywhere in your codebase. Creating a zod.d.ts file in your project root is a common convention.

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

.meta()

为了更方便的方法,使用 .meta() 方法在 z.globalRegistry 中注册一个模式。

🌐 For a more convenient approach, use the .meta() method to register a schema in z.globalRegistry.

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

调用 .meta() 不带参数时将检索模式的元数据。

🌐 Calling .meta() without an argument will retrieve the metadata for a schema.

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

元数据与特定的模式实例相关。这一点需要记住,尤其是因为 Zod 方法是不可变的——它们总是返回一个新的实例。

🌐 Metadata is associated with a specific schema instance. This is important to keep in mind, especially since Zod methods are immutable—they always return a new instance.

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() 方法是在 z.globalRegistry 中仅用一个 description 字段注册模式的简写。

🌐 The .describe() method is a shorthand for registering a schema in z.globalRegistry with just a description field.

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

自定义注册表

🌐 Custom registries

你已经看到了一个自定义注册表的简单示例:

🌐 You've already seen a simple example of a custom registry:

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

让我们看一些更高级的模式。

🌐 Let's look at some more advanced patterns.

引用推断类型

🌐 Referencing inferred types

元数据类型通常引用模式的推断类型是很有价值的。例如,你可能希望 examples 字段包含该模式输出的示例。

🌐 It's often valuable for the metadata type to reference the inferred type of a schema. For instance, you may want an examples field to contain examples of the schema's output.

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 来引用输入类型。

🌐 The special symbol z.$output is a reference to the schemas inferred output type (z.infer<typeof schema>). Similarly you can use z.$input to reference the input type.

限制模式类型

🌐 Constraining schema types

传递第二个通用类型给 z.registry() 以限制可以添加到注册表的模式类型。该注册表仅接受字符串模式。

🌐 Pass a second generic to z.registry() to constrain the schema types that can be added to a registry. This registry only accepts string schemas.

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