定义模式
要验证数据,你必须首先定义一个模式。模式表示类型,从简单的原始值到复杂的嵌套对象和数组。
🌐 To validate data, you must first define a schema. Schemas represent types, from simple primitive values to complex nested objects and arrays.
原语
🌐 Primitives
强制转换
🌐 Coercion
要将输入数据强制转换为适当的类型,请改用 z.coerce:
🌐 To coerce input data to the appropriate type, use z.coerce instead:
这些模式的强制类型会尝试将输入值转换为适当的类型。
🌐 The coerced variant of these schemas attempts to convert the input value to the appropriate type.
这些强制模式的输入类型默认是 unknown。要指定更具体的输入类型,请传递一个泛型参数:
🌐 The input type of these coerced schemas is unknown by default. To specify a more specific input type, pass a generic parameter:
字面量
🌐 Literals
字面模式表示一种字面类型,如 "hello world" 或 5。
🌐 Literal schemas represent a literal type, like "hello world" or 5.
表示 JavaScript 字面量 null 和 undefined :
🌐 To represent the JavaScript literals null and undefined:
要允许多个字面量值:
🌐 To allow multiple literal values:
要从字面模式中提取允许值的集合:
🌐 To extract the set of allowed values from a literal schema:
字符串
🌐 Strings
Zod 提供了一些内置的字符串验证和转换 API。要执行一些常见的字符串验证:
🌐 Zod provides a handful of built-in string validation and transform APIs. To perform some common string validations:
要执行一些简单的字符串转换:
🌐 To perform some simple string transforms:
字符串格式
🌐 String formats
要针对某些常见字符串格式进行验证:
🌐 To validate against some common string formats:
电子邮件
🌐 Emails
要验证电子邮件地址:
🌐 To validate email addresses:
默认情况下,Zod 使用一个相对严格的电子邮件正则表达式,旨在验证包含常见字符的普通电子邮件地址。它大致相当于 Gmail 强制执行的规则。要了解有关此正则表达式的更多信息,请参阅 这篇文章。
🌐 By default, Zod uses a comparatively strict email regex designed to validate normal email addresses containing common characters. It's roughly equivalent to the rules enforced by Gmail. To learn more about this regex, refer to this post.
要自定义电子邮件验证行为,你可以将自定义正则表达式传递给 pattern 参数。
🌐 To customize the email validation behavior, you can pass a custom regular expression to the pattern param.
Zod 导出了几个你可以使用的有用的正则表达式。
🌐 Zod exports several useful regexes you could use.
UUIDs
要验证 UUID:
🌐 To validate UUIDs:
要指定特定的 UUID 版本:
🌐 To specify a particular UUID version:
RFC 9562/4122 UUID 规范要求第 8 个字节的前两位为 10。其他类似 UUID 的标识符不强制此约束。要验证任何类似 UUID 的标识符:
🌐 The RFC 9562/4122 UUID spec requires the first two bits of byte 8 to be 10. Other UUID-like identifiers do not enforce this constraint. To validate any UUID-like identifier:
网址
🌐 URLs
要验证任何与 WHATWG 兼容的 URL:
🌐 To validate any WHATWG-compatible URL:
如你所见,这是相当宽松的。内部使用 new URL() 构造函数来验证输入;这种行为可能在不同的平台和运行时中有所不同,但它是在任何给定的 JS 运行时/引擎上验证 URI/URL 的最严格方法。
🌐 As you can see this is quite permissive. Internally this uses the new URL() constructor to validate inputs; this behavior may differ across platforms and runtimes but it's the mostly rigorous way to validate URIs/URLs on any given JS runtime/engine.
要根据特定的正则表达式验证主机名:
🌐 To validate the hostname against a specific regex:
要根据特定的正则表达式验证协议,请使用 protocol 参数。
🌐 To validate the protocol against a specific regex, use the protocol param.
网页 URL — 在许多情况下,你会想要专门验证网页 URL。以下是推荐的方案:
这将协议限制为 http/https,并确保主机名是使用 z.regexes.domain 正则表达式的有效域名:
要标准化 URL,请使用 normalize 标志。这将用 new URL() 返回的 标准化 URL 覆盖输入值。
🌐 To normalize URLs, use the normalize flag. This will overwrite the input value with the normalized URL returned by new URL().
ISO 日期时间
🌐 ISO datetimes
正如你可能注意到的,Zod 字符串包含一些与日期/时间相关的验证。这些验证是基于正则表达式的,因此它们不像完整的日期/时间库那样严格。然而,对于验证用户输入来说,它们非常方便。
🌐 As you may have noticed, Zod string includes a few date/time related validations. These validations are regular expression based, so they are not as strict as a full date/time library. However, they are very convenient for validating user input.
z.iso.datetime() 方法强制执行 ISO 8601;默认情况下,不允许使用时区偏移:
🌐 The z.iso.datetime() method enforces ISO 8601; by default, no timezone offsets are allowed:
要允许时区偏移:
🌐 To allow timezone offsets:
要允许非限定(无时区)日期时间:
🌐 To allow unqualified (timezone-less) datetimes:
用于限制允许的时间 precision。默认情况下,秒是可选的,并允许任意的亚秒精度。
🌐 To constrain the allowable time precision. By default, seconds are optional and arbitrary sub-second precision is allowed.
ISO 日期
🌐 ISO dates
z.iso.date() 方法验证格式为 YYYY-MM-DD 的字符串。
🌐 The z.iso.date() method validates strings in the format YYYY-MM-DD.
ISO 时间
🌐 ISO times
z.iso.time() 方法用于验证 HH:MM[:SS[.s+]] 格式的字符串。默认情况下,秒是可选的,子秒小数也是可选的。
🌐 The z.iso.time() method validates strings in the format HH:MM[:SS[.s+]]. By default seconds are optional, as are sub-second decimals.
不允许任何形式的偏移。
🌐 No offsets of any kind are allowed.
使用 precision 参数来限制允许的小数精度。
🌐 Use the precision parameter to constrain the allowable decimal precision.
IP 地址
🌐 IP addresses
IP 地址块 (CIDR)
🌐 IP blocks (CIDR)
验证使用 CIDR 表示法 指定的 IP 地址范围。
🌐 Validate IP address ranges specified with CIDR notation.
MAC 地址
🌐 MAC Addresses
验证标准 48 位 MAC 地址 IEEE 802。
🌐 Validate standard 48-bit MAC address IEEE 802.
JWTs
验证 JSON Web 令牌。
🌐 Validate JSON Web Tokens.
哈希值
🌐 Hashes
为了验证加密哈希值:
🌐 To validate cryptographic hash values:
默认情况下,z.hash() 期望十六进制编码,这是常规做法。你可以使用 enc 参数指定不同的编码:
🌐 By default, z.hash() expects hexadecimal encoding, as is conventional. You can specify a different encoding with the enc parameter:
自定义格式
🌐 Custom formats
定义你自己的字符串格式:
🌐 To define your own string formats:
该模式将产生 "invalid_format" 问题,这些问题比通过细化或 z.custom() 产生的 "custom" 错误更具描述性。
🌐 This schema will produce "invalid_format" issues, which are more descriptive than the "custom" errors produced by refinements or z.custom().
模板字面量
🌐 Template literals
新 — 于 zod@4.0 引入。
定义一个模板字面量模式:
🌐 To define a template literal schema:
z.templateLiteral API 可以处理任意数量的字符串字面量(例如 "hello")和模式。任何具有可分配给 string | number | bigint | boolean | null | undefined 的推断类型的模式都可以传递。
🌐 The z.templateLiteral API can handle any number of string literals (e.g. "hello") and schemas. Any schema with an inferred type that's assignable to string | number | bigint | boolean | null | undefined can be passed.
数字
🌐 Numbers
使用 z.number() 来验证数字。它允许任何有限数字。
🌐 Use z.number() to validate numbers. It allows any finite number.
Zod 实现了一些特定于数字的验证:
🌐 Zod implements a handful of number-specific validations:
如果(出于某种原因)你想验证 NaN,请使用 z.nan()。
🌐 If (for some reason) you want to validate NaN, use z.nan().
整数
🌐 Integers
要验证整数:
🌐 To validate integers:
BigInts
要验证 BigInt:
🌐 To validate BigInts:
Zod 包含一些特定于 bigint 的验证。
🌐 Zod includes a handful of bigint-specific validations.
布尔值
🌐 Booleans
要验证布尔值:
🌐 To validate boolean values:
日期
🌐 Dates
使用 z.date() 来验证 Date 实例。
🌐 Use z.date() to validate Date instances.
要自定义错误消息:
🌐 To customize the error message:
Zod 提供了一些特定于日期的验证。
🌐 Zod provides a handful of date-specific validations.
枚举
🌐 Enums
使用 z.enum 将输入与一组固定的允许 string 值进行验证。
🌐 Use z.enum to validate inputs against a fixed set of allowable string values.
支持类似枚举的对象字面量({ [key: string]: string | number })。
🌐 Enum-like object literals ({ [key: string]: string | number }) are supported.
你还可以传入外部声明的 TypeScript 枚举。
🌐 You can also pass in an externally-declared TypeScript enum.
Zod 4 — 这取代了 Zod 3 中的 z.nativeEnum() API。
请注意,不推荐使用 TypeScript 的 enum 关键字。not recommended。
.enum
要将模式的值提取为类似枚举的对象:
🌐 To extract the schema's values as an enum-like object:
.exclude()
要创建新的枚举架构并排除某些值:
🌐 To create a new enum schema, excluding certain values:
.extract()
要创建新的枚举架构并提取某些值:
🌐 To create a new enum schema, extracting certain values:
字符串布尔
🌐 Stringbools [#stringbool]
💎 Zod 4 新功能
在某些情况下(例如解析环境变量),将某些字符串“布尔值”解析为普通的 boolean 值是有价值的。为了支持这一点,Zod 4 引入了 z.stringbool():
🌐 In some cases (e.g. parsing environment variables) it's valuable to parse certain string "boolish" values to a plain boolean value. To support this, Zod 4 introduces z.stringbool():
自定义真值和假值:
🌐 To customize the truthy and falsy values:
默认情况下,模式是不区分大小写的;所有输入在与 truthy/falsy 值比较之前都会被转换为小写。要使其区分大小写:
🌐 By default the schema is case-insensitive; all inputs are converted to lowercase before comparison to the truthy/falsy values. To make it case-sensitive:
可选值
🌐 Optionals
使模式可选(即允许 undefined 输入)。
🌐 To make a schema optional (that is, to allow undefined inputs).
这将返回一个封装原始模式的 ZodOptional 实例。要提取内部模式:
🌐 This returns a ZodOptional instance that wraps the original schema. To extract the inner schema:
可空值
🌐 Nullables
使模式可为空(即允许输入 null)。
🌐 To make a schema nullable (that is, to allow null inputs).
这将返回一个封装原始模式的 ZodNullable 实例。要提取内部模式:
🌐 This returns a ZodNullable instance that wraps the original schema. To extract the inner schema:
将空值转换为空值
🌐 Nullish
要使模式 nullish(既可选又可为 null):
🌐 To make a schema nullish (both optional and nullable):
有关 nullish 概念的更多信息,请参阅 TypeScript 手册。
🌐 Refer to the TypeScript manual for more about the concept of nullish.
未知
🌐 Unknown
Zod 旨在一对一地映射 TypeScript 的类型系统。因此,Zod 提供了用于表示以下特殊类型的 API:
🌐 Zod aims to mirror TypeScript's type system one-to-one. As such, Zod provides APIs to represent the following special types:
从不
🌐 Never
任何值都无法通过验证。
🌐 No value will pass validation.
对象
🌐 Objects
定义一个对象类型:
🌐 To define an object type:
By default, all properties are required. To make certain properties optional:
默认情况下,未识别的键会从解析结果中去除:
🌐 By default, unrecognized keys are stripped from the parsed result:
z.strictObject
定义一个严格的模式,当发现未知键时会抛出错误:
🌐 To define a strict schema that throws an error when unknown keys are found:
z.looseObject
定义一个允许未知键通过的宽松模式:
🌐 To define a loose schema that allows unknown keys to pass through:
.catchall()
定义一个通用模式,用于验证任何未识别的键:
🌐 To define a catchall schema that will be used to validate any unrecognized keys:
.shape
访问内部模式:
🌐 To access the internal schemas:
.keyof()
要从对象模式的键创建 ZodEnum 模式:
🌐 To create a ZodEnum schema from the keys of an object schema:
.extend()
要向对象架构添加其他字段:
🌐 To add additional fields to an object schema:
这个 API 可用于覆盖现有字段!使用这个功能时要小心!如果两个模式共享键,B 将覆盖 A。
🌐 This API can be used to overwrite existing fields! Be careful with this power! If the two schemas share keys, B will override A.
替代方法:展开语法 — 你也可以通过完全创建一个新的对象模式来完全避免使用 .extend()。这会让生成的模式的严格程度一目了然。
你也可以使用此功能一次性合并多个对象。
🌐 You can also use this to merge multiple objects in one go.
这种方法有几个优点:
🌐 This approach has a few advantages:
- 它使用语言级特性(展开语法),而不是特定于库的 API
- 相同的语法适用于 Zod 和 Zod Mini
- 它在
tsc上更高效——.extend()方法在大型模式上可能很昂贵,并且由于 TypeScript 限制,当调用被链式调用时,成本会成倍增加 - 如果你愿意,你可以通过使用
z.strictObject()或z.looseObject()来更改生成的模式的严格程度
.safeExtend()
.safeExtend() 方法的工作方式类似于 .extend(),但它不会让你用不可赋值的模式覆盖现有属性。换句话说,.safeExtend() 的结果将具有推断类型,该类型 extends 原始类型(在 TypeScript 的意义上)。
🌐 The .safeExtend() method works similarly to .extend(), but it won't let you overwrite an existing property with a non-assignable schema. In other words, the result of .safeExtend() will have an inferred type that extends the original (in the TypeScript sense).
使用 .safeExtend() 来扩展包含细化的模式。(常规的 .extend() 在用于包含细化的模式时会抛出错误。)
🌐 Use .safeExtend() to extend schemas that contain refinements. (Regular .extend() will throw an error when used on schemas with refinements.)
.pick()
受 TypeScript 内置的 Pick 和 Omit 工具类型启发,Zod 提供了用于从对象模式中选择和省略某些键的专用 API。
🌐 Inspired by TypeScript's built-in Pick and Omit utility types, Zod provides dedicated APIs for picking and omitting certain keys from an object schema.
从此初始模式开始:
🌐 Starting from this initial schema:
To pick certain keys:
.omit()
要省略某些键:
🌐 To omit certain keys:
.partial()
为了方便,Zod 提供了一个专用的 API,用于将部分或全部属性设为可选,这一设计灵感来源于内置的 TypeScript 工具类型 Partial。
🌐 For convenience, Zod provides a dedicated API for making some or all properties optional, inspired by the built-in TypeScript utility type Partial.
要使所有字段可选:
🌐 To make all fields optional:
要使某些属性可选:
🌐 To make certain properties optional:
.required()
Zod 提供了一个 API,用于将某些或所有属性设置为必需,其灵感来自 TypeScript 的 Required 工具类型。
🌐 Zod provides an API for making some or all properties required, inspired by TypeScript's Required utility type.
要使所有属性必填:
🌐 To make all properties required:
要使某些属性成为必需属性:
🌐 To make certain properties required:
递归对象
🌐 Recursive objects
要定义自引用类型,在键上使用 getter。这让 JavaScript 能在运行时解析循环模式。
🌐 To define a self-referential type, use a getter on the key. This lets JavaScript resolve the cyclical schema at runtime.
虽然支持递归模式,但将循环数据传入 Zod 会导致无限循环。
你也可以表示相互递归类型:
🌐 You can also represent mutually recursive types:
所有对象 API(.pick()、.omit()、.required()、.partial() 等)都按预期工作。
🌐 All object APIs (.pick(), .omit(), .required(), .partial(), etc.) work as you'd expect.
循环错误
🌐 Circularity errors
由于 TypeScript 的限制,递归类型推断可能会很棘手,并且它只在某些情况下有效。一些更复杂的类型可能会触发像这样的递归类型错误:
🌐 Due to TypeScript limitations, recursive type inference can be finicky, and it only works in certain scenarios. Some more complicated types may trigger recursive type errors like this:
在这些情况下,你可以在有问题的 getter 上添加类型注释来解析错误:
🌐 In these cases, you can resolve the error with a type annotation on the offending getter:
数组
🌐 Arrays
定义一个数组模式:
🌐 To define an array schema:
访问数组元素的内部模式。
🌐 To access the inner schema for an element of the array.
Zod 实现了一些特定于数组的验证:
🌐 Zod implements a number of array-specific validations:
元组
🌐 Tuples
与数组不同,元组通常是固定长度的数组,每个索引指定不同的模式。
🌐 Unlike arrays, tuples are typically fixed-length arrays that specify different schemas for each index.
添加可变(“剩余”)参数:
🌐 To add a variadic ("rest") argument:
联合
🌐 Unions
联合类型(A | B)表示逻辑“或”。Zod 联合模式会按顺序检查输入是否符合每个选项。第一个验证成功的值将被返回。
🌐 Union types (A | B) represent a logical "OR". Zod union schemas will check the input against each option in order. The first value that validates successfully is returned.
要提取内部选项模式:
🌐 To extract the internal option schemas:
异或 (XOR)
🌐 Exclusive unions (XOR)
异或联合(XOR)是一种联合,其中必须恰好有一个选项匹配。与任何选项匹配即可成功的常规联合不同,如果没有选项匹配或者有多个选项匹配,z.xor() 将失败。
🌐 An exclusive union (XOR) is a union where exactly one option must match. Unlike regular unions that succeed when any option matches, z.xor() fails if zero options match OR if multiple options match.
当你想要确保选项之间的互斥性时,此功能非常有用:
🌐 This is useful when you want to ensure mutual exclusivity between options:
如果输入可以匹配多个选项,z.xor() 将会失败:
🌐 If the input could match multiple options, z.xor() will fail:
可区分联合
🌐 Discriminated unions
一个判别联合是一种特殊类型的联合,其中 a) 所有选项都是对象模式,并且 b) 共享特定的键(称为“判别器”)。根据判别器键的值,TypeScript 能够像预期的那样“缩小”类型签名。
🌐 A discriminated union is a special kind of union in which a) all the options are object schemas that b) share a particular key (the "discriminator"). Based on the value of the discriminator key, TypeScript is able to "narrow" the type signature as you'd expect.
你可以用一个普通的 z.union() 来表示它。但普通联合类型是天真的——它会按顺序检查输入是否符合每个选项,并返回第一个通过的选项。这对于大的联合类型来说可能很慢。
🌐 You could represent it with a regular z.union(). But regular unions are naive—they check the input against each option in order and return the first one that passes. This can be slow for large unions.
所以 Zod 提供了一个 z.discriminatedUnion() API,该 API 使用 鉴别键 来提高解析的效率。
🌐 So Zod provides a z.discriminatedUnion() API that uses a discriminator key to make parsing more efficient.
每个选项都应该是一个对象模式,其判别属性(在上面的示例中为status)对应某个字面值或一组值,通常是z.enum()、z.literal()、z.null()或z.undefined()。
🌐 Each option should be an object schema whose discriminator prop (status in the example above) corresponds to some literal value or set of values, usually z.enum(), z.literal(), z.null(), or z.undefined().
交叉点
🌐 Intersections
交叉类型(A & B)表示逻辑“与”。
🌐 Intersection types (A & B) represent a logical "AND".
这对于交叉两种对象类型很有用。
🌐 This can be useful for intersecting two object types.
在合并对象模式时,推荐使用 A.extend(B) 而不是交集。使用 .extend() 会给你一个新的对象模式,而 z.intersection(A, B) 返回一个 ZodIntersection 实例,该实例缺少诸如 pick 和 omit 这样的常用对象方法。
记录
🌐 Records
记录模式用于验证诸如 Record<string, string> 的类型。
🌐 Record schemas are used to validate types such as Record<string, string>.
z.record
键模式可以是任何可分配给 string | number | symbol 的 Zod 模式。
🌐 The key schema can be any Zod schema that is assignable to string | number | symbol.
要创建包含枚举定义的键的对象架构:
🌐 To create an object schemas containing keys defined by an enum:
新 — 从 v4.2 开始,Zod 正确支持记录中的数字键,这种方式更接近 TypeScript 本身的行为。当 number 模式用作记录键时,它将验证该键是否为有效的“数字字符串”。额外的数字约束(最小值、最大值、步长等)也将被验证。
z.partialRecord
Zod 4 — 在 Zod 4 中,如果你将 z.enum 作为 z.record() 的第一个参数传入,Zod 会全面检查输入中是否所有枚举值都存在作为键。此行为与 TypeScript 一致:
在 Zod 3 中,没有检查穷尽性。要复制旧行为,请使用 z.partialRecord()。
如果你想要一个部分记录类型,请使用 z.partialRecord()。这会跳过 Zod 通常在 z.enum() 和 z.literal() 键模式下执行的特殊完整性检查。
🌐 If you want a partial record type, use z.partialRecord(). This skips the special exhaustiveness checks Zod normally runs with z.enum() and z.literal() key schemas.
z.looseRecord
默认情况下,z.record() 会在键不符合键模式时产生错误。使用 z.looseRecord() 可以让不匹配的键保持不变地通过。这在与交集结合以建模多个模式属性时特别有用:
🌐 By default, z.record() errors on keys that don't match the key schema. Use z.looseRecord() to pass through non-matching keys unchanged. This is particularly useful when combined with intersections to model multiple pattern properties:
映射
🌐 Maps
集合
🌐 Sets
可以使用以下实用方法进一步约束设置的 Schema。
🌐 Set schemas can be further constrained with the following utility methods.
文件
🌐 Files
验证 File 实例:
🌐 To validate File instances:
Promise
🌐 Promises
已弃用 — 在 Zod 4 中,z.promise() 已被弃用。对 Promise 模式的有效使用几乎不存在。如果你怀疑一个值可能是 Promise,只需在使用 Zod 解析之前 await 它即可。
Instanceof
你可以使用 z.instanceof 来检查输入是否为某个类的实例。这对于验证输入是否符合从第三方库导出的类非常有用。
🌐 You can use z.instanceof to check that the input is an instance of a class. This is useful to validate inputs against classes that are exported from third-party libraries.
属性
🌐 Property
要根据 Zod 模式验证类实例的特定属性:
🌐 To validate a particular property of a class instance against a Zod schema:
z.property() API 可用于任何数据类型(但与 z.instanceof() 结合使用时最为有用)。
🌐 The z.property() API works with any data type (but it's most useful when used in conjunction with z.instanceof()).
细化
🌐 Refinements
每个 Zod 模式都会存储一个 refinements 数组。Refinements 是一种执行 Zod 未提供原生 API 的自定义验证的方法。
🌐 Every Zod schema stores an array of refinements. Refinements are a way to perform custom validation that Zod doesn't provide a native API for.
.refine()
精炼函数绝不应该抛弃。相反,他们应该返回一个虚假值来表示信号失败。投掷失误不会被 Zod 接住。
error
要自定义错误消息:
🌐 To customize the error message:
abort
默认情况下,检查中的验证问题被视为可继续的;也就是说,即使其中一个检查导致验证错误,Zod仍会按顺序执行所有检查。这通常是理想的,因为这意味着 Zod 可以一次性显示尽可能多的错误。
🌐 By default, validation issues from checks are considered continuable; that is, Zod will execute all checks in sequence, even if one of them causes a validation error. This is usually desirable, as it means Zod can surface as many errors as possible in one go.
要将特定的精炼标记为不可继续,请使用 abort 参数。如果检查失败,验证将终止。
🌐 To mark a particular refinement as non-continuable, use the abort parameter. Validation will terminate if the check fails.
path
要自定义错误路径,请使用 path 参数。这通常只在对象模式的上下文中有用。
🌐 To customize the error path, use the path parameter. This is typically only useful in the context of object schemas.
这将设置关联问题中的 path 参数:
🌐 This will set the path parameter in the associated issue:
要定义一个异步精炼,只需传入一个 async 函数:
🌐 To define an asynchronous refinement, just pass an async function:
如果你使用异步细化,你必须使用 .parseAsync 方法来解析数据!否则 Zod 会抛出错误。
when
注意 — 这是一个高级用户功能,并且绝对可能被滥用,从而增加源自你优化中的未被发现错误的概率。
默认情况下,如果已经遇到任何不可继续的问题,则不会运行细化。Zod 会小心确保值的类型签名正确,然后才将其传递到任何细化函数中。
🌐 By default, refinements don't run if any non-continuable issues have already been encountered. Zod is careful to ensure the type signature of the value is correct before passing it into any refinement functions.
在某些情况下,你可能希望对细化何时运行有更精细的控制。例如,考虑这个“确认密码”检查:
🌐 In some cases, you want finer control over when refinements run. For instance consider this "password confirm" check:
anotherField 上的错误将阻止密码确认检查的执行,即使该检查不依赖 anotherField。要控制精炼何时运行,请使用 when 参数:
🌐 An error on anotherField will prevent the password confirmation check from executing, even though the check doesn't depend on anotherField. To control when a refinement will run, use the when parameter:
.superRefine()
常规的 .refine API 仅生成一个带有 "custom" 错误代码的问题,但 .superRefine() 可以使用 Zod 的任何内部问题类型创建多个问题。
🌐 The regular .refine API only generates a single issue with a "custom" error code, but .superRefine() makes it possible to create multiple issues using any of Zod's internal issue types.
.check()
注意 — .check() API 是一个更底层的 API,通常比 .superRefine() 更复杂。它在性能敏感的代码路径中可能更快,但也更冗长。
编解码器
🌐 Codecs
新 — 在 Zod 4.1 中引入。有关更多信息,请参阅专门的 Codecs 页面。
编解码器是一种特殊类型的模式,它在两个其他模式之间实现双向转换。
🌐 Codecs are a special kind of schema that implement bidirectional transformations between two other schemas.
一个常规的 .parse() 操作执行前向变换。它调用编解码器的 decode 函数。
🌐 A regular .parse() operations performs the forward transform. It calls the codec's decode function.
你也可以选择使用顶层的 z.decode() 函数。与接受 unknown 输入的 .parse() 不同,z.decode() 期望一个强类型输入(在此示例中为 string)。
🌐 You can alternatively use the top-level z.decode() function. Unlike .parse() (which accepts unknown input), z.decode() expects a strongly-typed input (string in this example).
要执行反向变换,使用逆变换:z.encode()。
🌐 To perform the reverse transform, use the inverse: z.encode().
有关更多信息,请参阅专用的 Codecs 页面。该页面包含常用编解码器的实现,你可以将其复制/粘贴到你的项目中:
🌐 Refer to the dedicated Codecs page for more information. That page contains implementations for commonly-needed codecs that you can copy/paste into your project:
stringToNumberstringToIntstringToBigIntnumberToBigIntisoDatetimeToDateepochSecondsToDateepochMillisToDatejsonCodecutf8ToBytesbytesToUtf8base64ToBytesbase64urlToByteshexToBytesstringToURLstringToHttpURLuriComponentstringToBoolean
管道
🌐 Pipes
模式可以串联成“管道”。当与转换结合使用时,管道尤其有用。
🌐 Schemas can be chained together into "pipes". Pipes are primarily useful when used in conjunction with Transforms.
转换
🌐 Transforms
注意 — 对于双向转换,请使用 codecs。
转换是一种特殊类型的模式,用于执行单向转换。它们不是验证输入,而是接受任何内容并对数据进行某种转换。要定义一个转换:
🌐 Transforms are a special kind of schema that perform a unidirectional transformation. Instead of validating input, they accept anything and perform some transformation on the data. To define a transform:
转换函数绝不应该抛出异常。Zod 无法捕获抛出的错误。
要在转换中执行验证逻辑,请使用 ctx。要报告验证问题,请将新问题推送到 ctx.issues(类似于 .check() API)。
🌐 To perform validation logic inside a transform, use ctx. To report a validation issue, push a new issue onto ctx.issues (similar to the .check() API).
最常见的是,变换通常与 管道 一起使用。这种组合对于执行一些初步验证,然后将解析的数据转换为另一种形式非常有用。
🌐 Most commonly, transforms are used in conjunction with Pipes. This combination is useful for performing some initial validation, then transforming the parsed data into another form.
.transform()
将一些模式传入转换是一种常见模式,因此 Zod 提供了一个方便的 .transform() 方法。
🌐 Piping some schema into a transform is a common pattern, so Zod provides a convenience .transform() method.
转换也可以是异步的:
🌐 Transforms can also be async:
如果你使用异步转换,在解析数据时必须使用 .parseAsync 或 .safeParseAsync!否则 Zod 会抛出错误。
.preprocess()
将一个变换传入另一个模式是另一个常见模式,因此 Zod 提供了一个方便的 z.preprocess() 函数。
🌐 Piping a transform into another schema is another common pattern, so Zod provides a convenience z.preprocess() function.
默认值
🌐 Defaults
要设置模式的默认值:
🌐 To set a default value for a schema:
或者,你可以传递一个函数,每当需要生成默认值时,该函数都会重新执行:
🌐 Alternatively, you can pass a function which will be re-executed whenever a default value needs to be generated:
预错误
🌐 Prefaults
在 Zod 中,设置 默认 值会短路解析过程。如果输入是 undefined,则会立即返回默认值。因此,默认值必须可以赋值给模式的 输出类型。
🌐 In Zod, setting a default value will short-circuit the parsing process. If the input is undefined, the default value is eagerly returned. As such, the default value must be assignable to the output type of the schema.
有时,定义一个 预故障("预解析默认")值是有用的。如果输入是 undefined,将会解析预故障值。解析过程 不会 被短路。因此,预故障值必须可以分配给模式的 输入类型。
🌐 Sometimes, it's useful to define a prefault ("pre-parse default") value. If the input is undefined, the prefault value will be parsed instead. The parsing process is not short circuited. As such, the prefault value must be assignable to the input type of the schema.
如果你想通过一些可变的改进传递一些输入值,这也很有用。
🌐 This is also useful if you want to pass some input value through some mutating refinements.
捕获
🌐 Catch
使用 .catch() 来定义在验证错误时返回的备用值:
🌐 Use .catch() to define a fallback value to be returned in the event of a validation error:
或者,你可以传递一个函数,每当需要生成捕获值时,该函数都会重新执行。
🌐 Alternatively, you can pass a function which will be re-executed whenever a catch value needs to be generated.
品牌类型
🌐 Branded types
TypeScript 的类型系统是结构化的,这意味着两个结构上等价的类型被认为是相同的。
🌐 TypeScript's type system is structural, meaning that two types that are structurally equivalent are considered the same.
在某些情况下,在 TypeScript 中模拟名义类型是可取的。这可以通过标记类型(也称为“不透明类型”)来实现。
🌐 In some cases, it can be desirable to simulate nominal typing inside TypeScript. This can be achieved with branded types (also known as "opaque types").
在底层,这通过将“品牌”附加到模式推断出的类型来实现。
🌐 Under the hood, this works by attaching a "brand" to the schema's inferred type.
有了这个品牌,任何普通的(未品牌化的)数据结构都不再可分配给推断类型。你必须使用模式解析一些数据才能获得品牌化数据。
🌐 With this brand, any plain (unbranded) data structures are no longer assignable to the inferred type. You have to parse some data with the schema to get branded data.
请注意,品牌类型不会影响 .parse 的运行时结果。它只是一个仅限静态的构造。
默认情况下,只有输出类型会被标记。
🌐 By default, only the output type is branded.
要自定义此内容,向 .brand() 传递第二个泛型以指定品牌的方向。
🌐 To customize this, pass a second generic to .brand() to specify the direction of the brand.
只读
🌐 Readonly
要将模式标记为只读:
🌐 To mark a schema as readonly:
新模式的推断类型将标记为 readonly。请注意,在 TypeScript 中,这仅影响对象、数组、元组、Set 和 Map:
🌐 The inferred type of the new schemas will be marked as readonly. Note that in TypeScript, this only affects objects, arrays, tuples, Set, and Map:
输入将像平常一样被解析,然后结果将使用Object.freeze()冻结以防止修改。
🌐 Inputs will be parsed like normal, then the result will be frozen with Object.freeze() to prevent modifications.
JSON
要验证任何可 JSON 编码的值:
🌐 To validate any JSON-encodable value:
这是一个便捷的 API,它返回以下联合模式:
🌐 This is a convenience API that returns the following union schema:
函数
🌐 Functions
Zod 提供了一个 z.function() 工具,用于定义经过 Zod 验证的函数。通过这种方式,你可以避免将验证代码与业务逻辑混合在一起。
🌐 Zod provides a z.function() utility for defining Zod-validated functions. This way, you can avoid intermixing validation code with your business logic.
函数模式有一个 .implement() 方法,它接受一个函数并返回一个新函数,该新函数会自动验证其输入和输出。
🌐 Function schemas have an .implement() method which accepts a function and returns a new function that automatically validates its inputs and outputs.
如果输入无效,该函数将抛出 ZodError:
🌐 This function will throw a ZodError if the input is invalid:
如果你只关心验证输入,可以省略 output 字段。
🌐 If you only care about validating inputs, you can omit the output field.
使用 .implementAsync() 方法来创建一个异步函数。
🌐 Use the .implementAsync() method to create an async function.
自定义
🌐 Custom
你可以通过使用 z.custom() 为任何 TypeScript 类型创建 Zod 模式。这对于为 Zod 不直接支持的类型创建模式非常有用,例如模板字符串字面量。
🌐 You can create a Zod schema for any TypeScript type by using z.custom(). This is useful for creating schemas for types that are not supported by Zod out of the box, such as template string literals.
如果你不提供验证函数,Zod 将允许任何值。这可能很危险!
🌐 If you don't provide a validation function, Zod will allow any value. This can be dangerous!
你可以通过传递第二个参数来自定义错误信息和其他选项。这个参数的工作方式与 .refine 的 params 参数相同。
🌐 You can customize the error message and other options by passing a second argument. This parameter works the same way as the params parameter of .refine.
申请
🌐 Apply
使用 .apply() 将外部函数整合到 Zod 的方法链中:
🌐 Use .apply() to incorporate external functions into Zod's method chain:

