如何根据父对象的值验证 Zod 对象

问题描述 投票:0回答:1

我有一个像这样的zod模式:

export const memberSchema = z
  .object({
    name: z.string().min(3),
    lastname: z.string().min(3),
    nationality: zCountries,
    birthdate: z.date(),
    email: z.string().email(),
    tutor: z
      .object({
        name: z.union([z.string(), z.undefined()]),
        lastname: z.union([z.string(), z.undefined()]),
        documentType: z.union([zDocumentationType, z.undefined()]),
        documentValue: z.union([z.string(), z.undefined()]),
        email: z.union([z.string().email(), z.undefined()]),
        phone: z.union([z.string().regex(/^\d{9}$/), z.undefined()])
      })
  }).refine((data) => .....)

是否可以仅在出生日期未满 18 岁的情况下验证导师对象? 因为如果成员是 +18,则不需要此字段。

我知道如何在精炼函数中根据另一个字段来验证一个字段,但我不知道如何验证整个对象...

reactjs forms validation zod
1个回答
0
投票

您可以使用

superRefine
调用将问题添加到整个对象。例如:

export const memberSchema = z
  .object({
    name: z.string().min(3),
    lastname: z.string().min(3),
    nationality: zCountries,
    birthdate: z.date(),
    email: z.string().email(),
    tutor: tutorSchema.optional(),
  })
  .superRefine((obj, ctx) => {
    const ageInYears = getAgeInYears(obj.birthdate);
    if (ageInYears < 18 && obj.tutor === undefined) {
      ctx.addIssue({
        code: "custom",
        message: "Members under the age of 18 must have a tutor",
      });
    }
  });

console.log(
  memberSchema.safeParse({
    name: "Test",
    lastname: "Testerson",
    nationality: "USA",
    birthdate: new Date("2010-1-1"), // Some date less than 18 years ago
    email: "[email protected]",
  })
); // Logs failure with custom message

console.log(
  memberSchema.safeParse({
    name: "Test",
    lastname: "Testerson",
    nationality: "USA",
    birthdate: new Date("2010-1-1"), // Some date less than 18 years ago
    email: "[email protected]",
    tutor: {
      name: "Tutor",
      lastname: "Some tutor",
      phone: undefined,
      email: undefined,
      documentType: undefined,
      documentValue: undefined,
    },
  })
); // Logs success

请注意,从

Date
对象到其年龄(以年为单位)可能并不简单,因此我将其作为练习留给读者。

主要技巧是使导师字段可选,然后使用精炼说,“不,实际上,如果用户超过 18 岁,则必须定义它”。

关于类型的注释

不幸的是,一旦您知道用户未满 18 岁,这种方法就不会为您提供任何更可靠的类型保证。如果您希望类型系统为您跟踪这一点,您可以沿着

birthdate
拆分类型并使用
z.brand
附加附加信息,但这可能比它的价值更麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.