Zod基于表单字段的条件验证

dei*_*thy 2 typescript reactjs react-hook-form zod

我的表单中有一个status = 'DRAFT' | 'READY'枚举字段,是否可以zod根据该字段的值更改 lib 中的验证?

// validation passed
{
  name: "John",
  surname: null,
  status: "DRAFT"
}

// validation failed
{
  name: "John",
  surname: null,
  status: "READY"
}
Run Code Online (Sandbox Code Playgroud)

所以本质上如果从这里status === "READY"删除.min(1)

const schema = z.object({
  name: z.string(),
  surname: z.string().min(1),
  status: z.enum(["READY", "DRAFT"])
});
Run Code Online (Sandbox Code Playgroud)

Sou*_*man 5

您使用 s 得出的答案union是可能的。未来可能产生更好类型的另一种选择是利用 zod 的discriminatedUnion模式:

// placing shared fields in one place to avoid repetition
const base = z.object({
  name: z.string(),
});

const schema = z.discriminatedUnion(
  'status',
  [
    z.object({
      status: z.literal("DRAFT"),
      surname: z.string(),
    }).merge(base),
    z.object({
      status: z.literal("READY"),
      surname: z.string().min(1),
    }).merge(base),
  ],
);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我相信您最终会得到与union直接使用相同的推断类型,但是,这种方法对您可能想要区分的其他更改更具弹性。例如,如果DRAFT对象允许surname使用optional可区分联合,那么您可以细化为非可选类型 if statusis "READY"

通过union定义,该示例中的类型surname将始终string | undefined与 的值无关status