定义模式
要验证数据,您必须首先定义一个模式。模式代表类型,从简单的原始值到复杂的嵌套对象和数组。
原始类型
强制转换
若要将输入数据强制转换为适当的类型,请改用 z.coerce:
这些模式的强制转换版本尝试将输入值转换为适合的类型。
这些强制转换模式的输入类型默认为 unknown。要指定更具体的输入类型,请传递泛型参数:
字面量
字面量模式表示一种 字面量类型,例如 "hello world" 或 5。
表示 JavaScript 字面量 null 和 undefined:
允许多个字面量值:
从字面量模式中提取允许值集合:
字符串
Zod 提供了一些内置的字符串验证和转换 API。执行常见字符串验证:
执行简单的字符串转换:
字符串格式
验证常见字符串格式:
邮件
验证邮箱地址:
默认情况下,Zod 使用一种相对严格的邮箱正则表达式,设计用来验证包含常见字符的普通邮箱地址。大致相当于 Gmail 采用的规则。欲了解更多,参考这篇文章。
要自定义邮箱验证行为,可以向 pattern 参数传递一个自定义正则表达式。
Zod 导出了一些实用的正则表达式可供使用。
UUID
验证 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:
URL
验证任意 WHATWG 兼容 URL:
如您所见,这非常宽松。内部使用 new URL() 构造函数验证输入;此行为可能因平台和运行时而异,但这是在任何 JS 运行时/引擎上验证 URI/URL 的最严谨方法。
验证主机名是否匹配特定正则:
要验证协议是否匹配特定正则,使用 protocol 参数。
Web URLs — 许多情况下,您可能只想验证 Web URL。推荐的模式如下:
该配置限定协议为 http/https,并通过 z.regexes.domain 正则确保主机名为合法域名:
要规范化 URL,请使用 normalize 标志。这将用 new URL() 返回的 规范化 URL 覆盖输入值。
ISO 日期时间
正如您可能注意到的,Zod 字符串包含了一些与日期/时间相关的验证。这些验证是基于正则表达式的,因此它们没有完整的日期/时间库那么严格。然而,它们对于验证用户输入非常方便。
z.iso.datetime() 方法强制执行 ISO 8601;默认情况下,不允许时区偏移:
允许时区偏移:
允许无时区(本地)日期时间:
限制允许的时间 precision。默认情况下,秒数为可选且允许任意亚秒级精度。
ISO 日期
z.iso.date() 方法验证格式为 YYYY-MM-DD 的字符串。
ISO 时间
z.iso.time() 方法用于验证格式为 HH:MM[:SS[.s+]] 的字符串。默认情况下,秒是可选的,子秒小数也是可选的。
不允许任何形式的抵消。
使用 precision 参数来限制允许的小数精度。
IP 地址
IP 块 (CIDR)
验证使用CIDR 表示法的 IP 地址段。
MAC Addresses
Validate standard 48-bit MAC address IEEE 802.
JWTs
验证 JSON Web Tokens。
哈希
验证加密哈希值:
默认情况下,z.hash() 期望十六进制编码,这是常规做法。您可以使用 enc 参数指定不同的编码:
自定义格式
要定义您自己的字符串格式:
此模式将产生 "invalid_format" 问题,这些问题比通过细化或 z.custom() 产生的 "custom" 错误更具描述性。
模板字面量
新 — 在 zod@4.0 中引入。
定义模板字面量模式:
z.templateLiteral API 可以处理任意数量的字符串字面量(如 "hello")和模式。可传入任何推断类型可赋值给string | number | bigint | boolean | null | undefined的模式。
数字
使用 z.number() 验证数字。允许所有有限数字。
Zod 实现了若干特定数字的验证:
如果(因某些原因)想验证 NaN,使用 z.nan()。
整数
验证整数:
BigInt
验证 BigInts:
Zod 提供了一些针对 bigint 的验证。
布尔值
验证布尔值:
日期
使用 z.date() 验证 Date 实例。
自定义错误消息:
Zod 提供了一些针对日期的验证。
枚举
使用 z.enum 验证输入是否属于固定的允许字符串集合。
支持类似枚举的对象字面量 { [key: string]: string | number }。
你也可以传入一个外部声明的 TypeScript 枚举。
Zod 4 — 这取代了 Zod 3 中的 z.nativeEnum() API。
请注意,使用 TypeScript 的 enum 关键字并不推荐。
.enum
提取模式的值为类似枚举的对象:
.exclude()
创建新枚举模式,排除指定值:
.extract()
创建新枚举模式,仅包含指定值:
字符串布尔值
💎 Zod 4 新增
某些情况下(如解析环境变量),将某些字符串“布尔值”解析为纯 boolean 值非常有用。为支持此功能,Zod 4 引入了 z.stringbool():
自定义真值和假值:
默认情况下,模式是不区分大小写的;所有输入在与 truthy/falsy 值比较之前都会转换为小写。要使其区分大小写:
可选
使模式可选(即允许 undefined 输入)。
返回一个 ZodOptional 实例,包装了原模式。提取内层模式:
可空
使模式可空(即允许 null 输入)。
返回一个 ZodNullable 实例,包装了原模式。提取内层模式:
Nullish
使模式nullish(即可选且可空):
更多关于nullish概念,请参阅 TypeScript 手册。
Unknown
Zod 致力于与 TypeScript 类型系统一一对应,因此提供以下特殊类型的 API:
Never
没有任何值可以通过验证。
对象
定义对象类型:
默认所有属性必需。使某些属性可选:
默认情况下,未识别的键会从解析结果中剥除:
z.strictObject
定义严格模式,检测到未知键时报错:
z.looseObject
定义宽松模式,允许未知键通过:
.catchall()
要定义一个通用模式,用于验证任何未被识别的键:
.shape
访问内部模式:
.keyof()
从对象模式的键创建 ZodEnum 模式:
.extend()
为对象模式添加额外字段:
此 API 可用于覆盖现有字段!请小心使用此功能!如果两个模式共享键,B 将覆盖 A。
Alternative: spread syntax — You can alternatively avoid .extend() altogether by creating a new object schema entirely. This makes the strictness level of the resulting schema visually obvious.
您还可以使用此功能一次合并多个对象。
这种方法有几个优点:
- 它使用语言级特性(扩展语法),而不是特定于库的 API
- 相同的语法在 Zod 和 Zod Mini 中都适用
- 它更具
tsc效率——在大型模式上,.extend()方法可能会很昂贵,并且由于 TypeScript 的限制,当调用链式调用时,它的成本会呈平方增长 - 如果您愿意,可以通过使用
z.strictObject()或z.looseObject()来更改结果模式的严格性级别
.safeExtend()
.safeExtend() 方法的工作方式类似于 .extend(),但它不会允许你用不可赋值的模式覆盖已有属性。换句话说,.safeExtend() 的结果将具有一个推断类型,该类型在 TypeScript 的意义上 extends 原始类型。
使用 .safeExtend() 来扩展包含细化的模式。(常规的 .extend() 在用于包含细化的模式时会抛出错误。)
.pick()
借鉴 TypeScript 的内置工具类型 Pick 和 Omit,Zod 提供了专用 API 用于从对象模式中选择/剔除某些键。
初始模式:
选择某些键:
.omit()
剔除某些键:
.partial()
为方便起见,Zod 提供了专门 API,使部分或所有属性变为可选,灵感来自 TypeScript 内置的 Partial。
使所有字段可选:
使指定属性可选:
.required()
Zod 提供了一个使部分或所有属性必需的 API,灵感来自 TypeScript 内置的 Required。
使所有属性必需:
使指定属性必需:
递归对象
定义自引用类型,使用键的getter。这让 JavaScript 在运行时解析循环模式。
虽支持递归模式,但传入循环数据将导致无限循环。
也可以表示互相递归的类型:
所有对象 API(如 .pick()、.omit()、.required()、.partial() 等)均如预期工作。
循环错误
由于 TypeScript 限制,递归类型推断可能出现问题,只在某些场景有效。复杂类型可能触发如下递归类型错误:
此时,您可以在出错 getter 上加类型注解解决:
数组
定义数组模式:
访问数组元素的内层模式:
Zod 实现了若干数组特定验证:
元组
元组通常是固定长度数组,每个索引指定不同的模式。
添加可变长("剩余")参数:
联合类型
联合类型(A | B)代表逻辑“或”。Zod 联合模式依次检查输入,返回第一个验证成功的选项。
访问内部选项模式:
排他联合(XOR)
排他联合(XOR)是一种联合,其中必须恰好有一个选项匹配。与普通联合只要有任意一个选项匹配就成功不同,z.xor()在没有选项匹配或有多个选项匹配时都会失败。
当你想确保选项之间互斥时,这很有用:
如果输入可以匹配多个选项,z.xor() 将会失败:
带分辨字段的联合
带分辨字段的联合 是一种特殊联合,要求 a) 所有选项均为对象模式且 b) 共享特定键(“分辨字段”)。根据分辨字段的值,TypeScript 能精确缩小类型。
可以用常规 z.union() 表示。但常规联合是朴素的—依序测试选项,返回首个成功。大联合时可能较慢。
Zod 提供了 z.discriminatedUnion(),通过分辨字段提高解析效率。
每个选项应该是一个 对象模式,其区分符属性(上面示例中的 status)对应某个字面值或一组值,通常是 z.enum()、z.literal()、z.null() 或 z.undefined()。
交叉类型
交叉类型 (A & B) 代表逻辑“且”。
这对合并两个对象类型很有用。
在合并对象模式时,优先使用 A.extend(B) 而不是交集。使用 .extend() 将为您提供一个新的对象模式,而 z.intersection(A, B) 返回一个 ZodIntersection 实例,该实例缺少像 pick 和 omit 这样的公共对象方法。
Record 类型
Record 模式用于验证如 Record<string, string> 类型。
z.record
键模式可为任何可赋值给 string | number | symbol 的 Zod 模式。
使用枚举定义键的对象模式:
z.partialRecord
Zod 4 — 在 Zod 4 中,若将 z.enum 传给 z.record() 作为第一个参数,Zod 会详尽检查输入对象是否包含所有枚举值作为键。此行为与 TypeScript 保持一致:
在 Zod 3 中,没有检查穷尽性。要复制旧的行为,请使用 z.partialRecord()。
若需定义部分 Record 类型,使用 z.partialRecord() 。此方法跳过 Zod 对 z.enum() 和 z.literal() 键模式的详尽检查。
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:
Map 类型
Set 类型
Set 模式可用以下方法进一步约束。
文件
验证 File 实例:
Promise
已弃用 — z.promise() 在 Zod 4 中已弃用。有效的使用场景极少。若怀疑值是 Promise,应在 Zod 验证前先 await。
instanceof 验证
使用 z.instanceof 验证输入是否为指定类的实例。适合验证来自第三方库的类实例。
属性
要验证类实例的特定属性是否符合 Zod 模式:
z.property() API 可以与任何数据类型一起使用(但在与 z.instanceof() 结合使用时最为有效)。
精炼验证
每个 Zod 模式都存有一组精炼数组。精炼用于执行 Zod 本身无内置 API 的自定义验证。
.refine()
精炼函数不应抛异常,且应返回假值表示失败。抛出错误不被 Zod 捕获。
error
要自定义错误消息:
abort
默认情况下,验证问题视为可继续,即所有检查都会依次执行,即便前面发生错误。此行为通常有利,可一次发现尽可能多错误。
要将特定的细化标记为不可继续,请使用abort参数。如果检查失败,验证将终止。
path
要自定义错误路径,请使用 path 参数。这通常仅在对象模式的上下文中有用。
这会将 path 设置为相关问题:
要定义一个异步细化,只需传递一个 async 函数:
若使用异步精炼,解析数据时必须调用 .parseAsync ,否则 Zod 会抛错。
when
注意 — 这是一个高级用户功能,绝对可能被滥用,从而增加未捕获错误的概率,这些错误源自于您的修饰。
默认情况下,如果已经遇到任何不可继续的问题,修饰将不会运行。Zod 会仔细确保值的类型签名在传递给任何修饰函数之前是正确的。
在某些情况下,您希望更精细地控制何时运行优化。例如,考虑这个“密码确认”检查:
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 的任何 内部问题类型 创建多个问题成为可能。
.check()
Note — The .check() API is a more low-level API that's generally more complex than .superRefine(). It can be faster in performance-sensitive code paths, but it's also more verbose.
编解码器
新 — 在 Zod 4.1 中引入。有关更多信息,请参阅专门的 编解码器 页面。
编解码器是一种特殊的模式,实现在两个其他模式之间的 双向转换。
常规的 .parse() 操作执行 前向变换。它调用编解码器的 decode 函数。
您可以选择使用顶级的 z.decode() 函数。与接受 unknown 输入的 .parse() 不同,z.decode() 期望一个强类型的输入(在此示例中为 string)。
要执行反向变换,请使用反函数:z.encode()。
请参阅专门的 编解码器 页面以获取更多信息。该页面包含您可以复制/粘贴到项目中的常用编解码器的实现:
stringToNumberstringToIntstringToBigIntnumberToBigIntisoDatetimeToDateepochSecondsToDateepochMillisToDatejsonCodecutf8ToBytesbytesToUtf8base64ToBytesbase64urlToByteshexToBytesstringToURLstringToHttpURLuriComponentstringToBoolean
管道
模式可以链接在一起形成“管道”。管道在与转换结合使用时特别有用。
变换(Transforms)
注意 — 对于双向转换,请使用 codecs。
转换是一种特殊的模式,执行单向转换。它们不验证输入,而是接受任何内容并对数据进行某种转换。要定义一个转换:
转换函数不应抛出异常。Zod不会捕获抛出的错误。
在变换中执行验证逻辑,使用 ctx。添加验证问题,推入 ctx.issues(类似.check() API)。
变换通常与管道联合使用。此组合方便在执行初步验证后,将解析数据转换为另一形式。
.transform()
将管道输入转换,常用模式,Zod 提供 .transform() 便捷方法。
变换可异步:
若使用异步变换,解析数据时必须用 .parseAsync 或 .safeParseAsync,否则 Zod 会抛错。
.preprocess()
将变换管道至另一个模式也常见,Zod 提供 z.preprocess() 便捷函数。
默认值
为模式设置默认值:
也可传入函数,每次需生成默认值时执行:
预故障值(Prefaults)
在 Zod 中,设置默认值会短路解析。若输入为 undefined,会立即返回默认值。因此默认值必须赋值给模式的输出类型。
有时定义预故障值(“预解析默认”)更实用。若输入为 undefined,将替代性地先解析预故障值,解析过程不短路。因此,预故障值必须赋值给模式的输入类型。
若希望在一些变异型精炼中使用输入值,此法有用。
捕获值(Catch)
使用 .catch() 定义验证错误时的备用值:
或传入函数,每次生成捕获值时执行:
品牌类型
TypeScript 类型系统是结构化的,结构相同的类型被视为相同。
某些情况中,想在 TypeScript 内模拟标称类型,可用品牌类型(又称“不透明类型”)。
其原理是为模式推断类型附加“品牌”。
使用此品牌后,任何普通(无品牌)数据结构都不再可分配给推断类型。你必须使用模式解析一些数据,以获得带品牌的数据。
请注意,品牌类型不会影响 .parse 的运行时结果。它只是一个仅用于静态的结构。
默认情况下,只有输出类型是带品牌的。
要自定义此项,请向 .brand() 传递第二个泛型以指定品牌的方向。
只读
使模式只读:
新模式推断类型会标记为 readonly。注意,在 TypeScript 中,这只影响对象、数组、元组、Set 和 Map:
输入会像往常一样被解析,结果使用 Object.freeze() 冻结,防止修改。
JSON
验证任意 JSON 可编码值:
此为便捷 API,返回如下联合模式:
函数
Zod 提供 z.function() 工具定义经过 Zod 验证的函数。避免验证码混入业务逻辑。
函数模式拥有 .implement() 方法,接受函数,返回自动验证输入输出的新函数。
输入验证失败时抛 ZodError:
若只关心验证输入,可省略 output 字段。
使用 .implementAsync() 方法创建一个异步函数。
自定义
您可以通过使用 z.custom() 为任何 TypeScript 类型创建 Zod 模式。这对于为 Zod 默认不支持的类型(例如模板字符串字面量)创建模式非常有用。
如果您不提供验证函数,Zod 将允许任何值。这可能是危险的!
您可以通过传递第二个参数来自定义错误消息和其他选项。此参数的工作方式与 .refine 的 params 参数相同。

