菜单

联合和交叉 Schema

相关源文件

本页面探讨了 Zod 中两种强大的模式组合机制:联合模式和交叉模式。虽然两者都能通过组合模式创建更复杂的验证模式,但它们的操作方式根本不同。

  • 联合模式验证输入是否匹配所提供的任何模式(或逻辑)
  • 交叉模式验证输入是否匹配所提供的所有模式(与逻辑)

对于对象模式特有的组合方法,如 .extend().merge().pick().omit(),请参阅对象模式页面。

联合模式

联合模式允许您创建一个接受与所提供任何模式匹配的值的模式。它们在内部实现为 ZodUnion 类。

创建联合模式

有两种方法可以创建联合模式

两种方法都会创建相同类型的模式,但当基于现有模式构建时,.or() 方法可能更方便。

来源:README.md118-121 README.md884-888

验证过程

当针对联合模式验证输入时,Zod 会执行以下操作:

  1. 按照提供的顺序尝试每个模式
  2. 返回第一个成功验证输入的模式的结果
  3. 如果所有模式都失败,则抛出包含合并问题信息的 ZodError

模式的顺序很重要,因为 Zod 会返回第一个匹配模式的结果。如果您的模式存在重叠,请仔细考虑它们的顺序。

来源:src/__tests__/unions.test.ts22-33

联合模式属性

联合模式通过 options 属性提供对其组成模式的访问

这对于对联合组件进行编程操作非常有用。

来源:src/__tests__/unions.test.ts51-57

联合错误处理

当联合中的所有模式都无法验证输入时,Zod 需要决定报告哪些错误。它使用一种复杂的算法,该算法会:

  1. 优先处理“脏”结果(验证失败)而非“中止”结果(类型不匹配)
  2. 尝试提供最具体和最有用的错误信息

实际上,这意味着您会收到最相关的错误消息,而不是一份令人困惑的输入失败方式列表。

来源:src/__tests__/unions.test.ts35-49

区分联合类型

可辨别联合是一种特殊类型的联合模式,它针对包含一个通用“辨别属性”以确定其结构的对象进行了优化。

创建可辨别联合

第一个参数是辨别属性的名称,第二个参数是对象模式数组。每个模式必须:

  1. 包含辨别属性
  2. 使用 z.literal() 作为辨别值
  3. 与其他模式相比具有唯一的辨别值

来源:README.md891-911

可辨别联合的工作原理

可辨别联合比普通联合更高效,因为它们会:

  1. 立即检查辨别属性是否存在
  2. 使用辨别值精确选择一个模式进行验证
  3. 如果验证失败,仅显示与所选模式相关的错误

这使得可辨别联合在处理对象模式时比普通联合更高效、更用户友好。

来源:README.md891-903

使用可辨别联合

与普通联合类似,您可以通过 options 属性访问组成模式。

要组合具有相同辨别属性的多个可辨别联合

来源:README.md913-930

交叉模式

交叉模式创建的模式要求值匹配所有提供的模式。它们对于组合验证要求特别有用。

创建交叉模式

有两种方法可以创建交叉模式

两种方法都会创建一个 ZodIntersection 模式,要求输入同时通过两个组成模式的验证。

来源:README.md124-125

验证过程

当针对交叉模式验证输入时,Zod 会执行以下操作:

  1. 针对第一个(左侧)模式验证输入
  2. 如果通过,则针对第二个(右侧)模式验证
  3. 如果两者都通过,则尝试合并验证结果
  4. 返回合并结果,如果无法合并则抛出错误

来源:src/__tests__/intersection.test.ts74-121

对象模式交叉

交叉模式最常见的用途是组合对象模式。结果要求同时包含两个模式的所有属性。

当交叉对象模式时,未知键的行为(严格、直通等)会继承自第二个(右侧)模式。

来源:src/__tests__/intersection.test.ts6-24

嵌套对象交叉

交叉模式通过递归合并其结构来处理深度嵌套的对象模式。

来源:src/__tests__/intersection.test.ts26-44

数组模式交叉

交叉模式也适用于数组,要求数组项满足所有模式。

来源:src/__tests__/intersection.test.ts46-72

交叉模式的局限性

并非所有模式都能有意义地交叉。当出现以下情况时,Zod 将抛出代码为 invalid_intersection_types 的错误:

  1. 模式以不同方式转换其数据
  2. 模式具有不兼容的输出类型
  3. 模式的验证结果无法合理合并

来源:src/__tests__/intersection.test.ts74-121

选择正确的模式组合器

主要选择标准

组合器何时使用何时避免
联合输入应匹配任意模式您需要组合对象属性
可辨别联合基于字段值的不同对象结构对象不共享通用字段
交叉输入必须满足所有模式模式以不同方式转换数据
对象方法 (.extend, .merge)在对象上添加/组合属性处理非对象模式

来源:README.md118-125 README.md652-681