网站搜索

reactjs - 使用表单验证器 ZOD 的 discriminatedUnion() 函数来区分三种表单


ValidationSchema = z.object({
AuthenticationBlock: z.object({
  ChoiceOfForm: z.enum()
  DataBlock: z.discriminatedUnion(ChoiceOfForm, [
     z.object({ ChoiceOfForm = 1, empty fields}) //corresponds to the basic form
     z.object({ ChoiceOfForm = 2, just username/pw fields) //corresponds to less basic form
     z.object({ ChoiceOfForm = 3, user/pw + many fields}) //corresponds to advanced form
    ])
  })
})

对象示例:

export type AuthenticationFormValues = {
    AuthenticationBlock?: {
        choice?: AuthenticationFormChoice | undefined;
        data: {
            password?: string;
            username?: string;
            formAuthenticationConfig?: {
                formUrl?: string;
                javaScriptLoadingDelayInMilliseconds?: number;
                forceLogin?: boolean;
                customLoginSequence?: string;
                authenticationFailed?: FormAuthenticationFailedConfiguration;
            };
        };
    };
};

choiceOfForm 是一个 ENUM,对应三个单选按钮,它们会展开不同的表单(1、2 或 3)。我想使用 ZOD 的 discriminatedUnion() 函数,根据选择的 choiceOfForm(1、2 或 3)启用正确的表单验证块。有没有办法将 choiceOfForm 变量传递给 discriminatedUnion(choiceOfForm, ...) 来实现这个功能?

谢谢

答案#1

我认为你可以通过类似这样的东西来实现你想要的效果:

import { z } from "zod";

enum ChoiceOfForm {
  Option1 = 1,
  Option2 = 2,
  Option3 = 3
}

// Defining this once since it's shared between two of the arms.
const PasswordFields = z.object({
  password: z.string(),
  email: z.string().email()
});

const schema = z.discriminatedUnion("choice", [
  z.object({
    choice: z.literal(undefined),
  }),
  z.object({
    choice: z.literal(ChoiceOfForm.Option1)
  }),
  z.object({
    choice: z.literal(ChoiceOfForm.Option2)
  }).merge(PasswordFields),
  z.object({
    choice: z.literal(ChoiceOfForm.Option3),
    extraOption: z.number()
  }).merge(PasswordFields)
]);

Zod 的 discriminatedUnion 函数将你将要用于区分的键作为第一个参数,以及联合的每个“分支”的模式列表。请注意,由于 z.literal(undefined) 选项,几乎任何对象都可以使用该模式成功解析。你可能想要省略这种可能性,但我不确定你的业务需求。

如果你成功使用这个模式解析某些内容,你可以使用 switch 或 if 语句检查 choice 的值,并像处理普通判别联合一样缩小类型。