Zod logo

面向库作者

本页面主要供在 Zod 上构建工具的库作者使用。

¥This page is primarily intended for consumption by library authors who are building tooling on top of Zod.

如果你是库作者,并且认为本页面应该包含一些额外的指导,请提交一个问题!

¥If you are a library author and think this page should include some additional guidance, please open an issue!

我需要依赖 Zod 吗?

¥Do I need to depend on Zod?

首先,请确保你需要依赖 Zod。

¥First things first, make sure you need to depend on Zod at all.

如果你正在构建一个接受用户定义模式来执行黑盒验证的库,则可能不需要专门与 Zod 集成。请参考 标准 Schema。它是 TypeScript 生态系统中大多数流行验证库(参见 完整列表)都实现的共享接口,包括 Zod。

¥If you're building a library that accepts user-defined schemas to perform black-box validation, you may not need to integrate with Zod specifically. Instead look into Standard Schema. It's a shared interface implemented by most popular validation libraries in the TypeScript ecosystem (see the full list), including Zod.

如果你接受用户定义的模式并将其视为 "黑盒" 验证器,则此规范非常有效。对于任何兼容的库,你可以提取推断的输入/输出类型,验证输入并返回标准化错误。

¥This spec works great if you accept user-defined schemas and treat them like "black box" validators. Given any compliant library, you can extract inferred input/output types, validate inputs, and get back a standardized error.

如果你需要 Zod 的特定功能,请继续阅读。

¥If you need Zod specific functionality, read on.

如何配置对等依赖?

¥How to configure peer dependencies?

任何基于 Zod 构建的库都应在 "peerDependencies" 中包含 "zod"。这允许你的用户使用 "自带 Zod"。

¥Any library built on top of Zod should include "zod" in "peerDependencies". This lets your users "bring their own Zod".

// package.json
{
  // ...
  "peerDependencies": {
    "zod": "^3.25.0"
  }
}

在开发过程中,你需要满足自己的对等依赖要求,为此,请将 "zod" 也添加到你的 "devDependencies" 中。

¥During development, you need to meet your own peer dependency requirement, to do so, add "zod" to your "devDependencies" as well.

// package.json
{
  "peerDependencies": {
    "zod": "^3.25.0"
  },
  "devDependencies": {
    "zod": "^3.25.0"
  }
}

如何支持 Zod 4?

¥How to support Zod 4?

要支持 Zod 4,请将 "zod" 对等依赖的最低版本更新为 ^3.25.0

¥To support Zod 4, update the minimum version for your "zod" peer dependency to ^3.25.0.

// package.json
{
  // ...
  "peerDependencies": {
    "zod": "^3.25.0"
  }
}

v3.25.0 开始,Zod 4 可在 /v4 子路径上使用。

¥Starting with v3.25.0, Zod 4 is available at a /v4 subpath.

import * as z4 from "zod/v4/core";

库代码不应从包根目录("zod")导入!相反,从特定于版本的子路径导入:"zod/v3""zod/v4/core"。这样,你的代码就可以在未来免受主要版本升级的影响。

¥Library code should not import from the package root ("zod")! Instead, import from the version-specific subpaths: "zod/v3" and "zod/v4/core". This way, your code is future-proofed against major version bumps down the line.

如何同时支持 Zod 3 和 Zod 4?

¥How to support Zod 3 and Zod 4 simultaneously?

v3.25.0 开始,该包在各自的子路径中包含 Zod 3 和 Zod 4 的副本。这使得同时支持两个版本变得容易。

¥Starting in v3.25.0, the package contains copies of both Zod 3 and Zod 4 at their respective subpaths. This makes it easy to support both versions simultaneously.

import * as z3 from "zod/v3";
import * as z4 from "zod/v4/core";
 
type Schema = z3.ZodTypeAny | z4.$ZodType;
 
function acceptUserSchema(schema: z3.ZodTypeAny | z4.$ZodType) {
  // ...
}

要在运行时区分 Zod 3 和 Zod 4 的模式,请检查 "_zod" 属性。此属性仅在 Zod 4 模式中定义。

¥To differentiate between Zod 3 and Zod 4 schemas at runtime, check for the "_zod" property. This property is only defined on Zod 4 schemas.

import type * as z3 from "zod/v3";
import type * as v4 from "zod/v4/core";
 
declare const schema: z3.ZodTypeAny | v4.$ZodType;
 
if ("_zod" in schema) {
  schema._zod.def; // Zod 4 schema
} else {
  schema._def; // Zod 3 schema
}

如何同时支持 Zod 和 Zod Mini?

¥How to support Zod and Zod Mini simultaneously?

你的库代码应该只从 zod/v4/core 导入。此子包定义了 zod/v4zod/v4-mini 之间共享的接口、类和实用程序。

¥Your library code should only import from zod/v4/core. This sub-package defines the interfaces, classes, and utilities that are shared between zod/v4 and zod/v4-mini.

// library code
import * as z from "zod/v4/core";
 
export function acceptObjectSchema<T extends z.$ZodObject>(schema: T){
  // parse data
  z.parse(schema, { /* somedata */});
  // inspect internals
  schema._zod.def.shape;
}

通过基于共享基接口构建,你可以同时可靠地支持这两个子包。此函数可以接受 zod/v4zod/v4-mini 模式。

¥By building against the shared base interfaces, you can reliably support both sub-packages simultaneously. This function can accept both zod/v4 and zod/v4-mini schemas.

// user code
import { acceptObjectSchema } from "your-library";
 
// Zod 4
import * as z from "zod/v4";
acceptObjectSchema(z.object({ name: z.string() }));
 
// Zod 4 Mini
import * as zm from "zod/v4-mini";
acceptObjectSchema(zm.object({ name: zm.string() }))

有关更多信息,请参阅 Zod 核心

¥Refer to the Zod Core page for more information on the contents of the core sub-library.

如何接受用户定义的模式?

¥How to accept user-defined schemas?

接受用户定义的模式是任何基于 Zod 构建的库的基本操作。本节概述了执行此操作的最佳实践。

¥Accepting user-defined schemas is the a fundamental operation for any library built on Zod. This section outlines the best practices for doing so.

刚开始时,可​​能很容易编写一个接受 Zod 模式的函数,如下所示:

¥When starting out, it may be tempting to write a function that accepts a Zod schema like this:

import * as z from "zod/v4";
 
function inferSchema<T>(schema: z.core.$ZodType<T>) {
  return schema;
}

这种方法是错误的,并且限制了 TypeScript 正确推断参数的能力。无论你传入什么,schema 的类型都将是 ZodType 的实例。

¥This approach is incorrect, and limits TypeScript's ability to properly infer the argument. No matter what you pass in, the type of schema will be an instance of ZodType.

inferSchema(z.string());
// => z.core.$ZodType<string>

这种方法会丢失类型信息,即输入实际上是哪个子类(在本例中为 ZodString)。这意味着你无法在 inferSchema 的结果上调用任何特定于字符串的方法,例如 .min()。相反,你的泛型参数应该扩展核心 Zod 模式接口:

¥This approach loses type information, namely which subclass the input actually is (in this case, ZodString). That means you can't call any string-specific methods like .min() on the result of inferSchema. Instead, your generic parameter should extend the core Zod schema interface:

function inferSchema<T extends z.core.$ZodType>(schema: T) {
  return schema;
}
 
inferSchema(z.string());
// => ZodString

结果现在具有完整且正确的类型,你可以提取并使用模式的推断类型:

¥The result is now fully and properly typed, you can extract & use the inferred type of the schema:

function parseData<T extends z.ZodTypeAny>(data: unknown, schema: T): z.output<T> {
  return schema.parse(data);
}
 
parseData("sup", z.string());
// => string

要将输入模式限制为特定子类:

¥To constrain the input schema to a specific subclass:

 
import * as z from "zod/v4";
 
// only accepts object schemas
function inferSchema<T>(schema: z.core.$ZodObject) {
  return schema;
}

要限制输入模式的推断输出类型:

¥To constrain the inferred output type of the input schema:

 
import * as z from "zod/v4";
 
// only accepts string schemas
function inferSchema<T extends z.core.$ZodType<string>>(schema: T) {
  return schema;
}
 
inferSchema(z.string()); // ✅ 
 
inferSchema(z.number()); 
// ❌ The types of '_zod.output' are incompatible between these types. 
// // Type 'number' is not assignable to type 'string'

On this page