You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Zod实现对象至少一个属性通过验证?

Zod 实现“至少一个属性符合规则”的验证方案

你之前的写法问题在于:先定义了要求name和email必须同时符合各自规则的对象 schema,所以只要其中一个属性不满足(比如name长度不足),在进入refine之前就会触发验证错误,根本走不到后续的判断逻辑;而且你的refine仅检查属性是否存在,没有验证属性是否符合规则。

下面是两种优雅的实现方式:

方案一:可选属性 + 精细化校验(推荐)

先将两个属性设为可选,再通过refine结合safeParse检查至少一个属性符合自身规则:

// 抽离单个属性的验证规则,提升复用性
const validName = z.string().min(3);
const validEmail = z.string().min(3);

const userSchema = z.object({
  name: validName.optional(),
  email: validEmail.optional()
}).refine(
  (data) => {
    // 验证name是否符合规则,或email是否符合规则
    return validName.safeParse(data.name).success || validEmail.safeParse(data.email).success;
  },
  {
    message: "必须提供至少3个字符的姓名,或至少3个字符的邮箱",
    // 可选:指定错误路径,让错误提示更精准
    path: []
  }
);

这种方式的优势:

  • 允许对象仅包含name或email中的一个
  • 仅当两个属性都不符合规则(或都不存在)时,才会抛出验证错误
  • 错误提示清晰,用户能明确知道需要满足的条件

方案二:联合类型分支校验

如果希望明确拆分两种合法场景(有合法name,或有合法email),可以使用z.union:

const userSchema = z.union([
  // 场景1:包含符合规则的name,email可选(无需验证)
  z.object({ name: z.string().min(3) }).partial({ email: true }),
  // 场景2:包含符合规则的email,name可选(无需验证)
  z.object({ email: z.string().min(3) }).partial({ name: true })
]);

如果需要严格限制另一个属性不能存在,可以把partial替换为omit:

// 仅允许存在name,不允许有email属性
z.object({ name: z.string().min(3) }).omit({ email: true })

内容的提问来源于stack exchange,提问作者Korer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:11:07