我试图用Zod和react-hook-form验证一个表单,我需要根据其他字段的值设置一些必填字段.下面是我的schema:

const formSchema = z.object({
    cli_rut: z.string(),
    cli_persona_natural: z.enum(["SI", "NO"]),
    cli_nombres: z.string().optional(),
    cli_apellido_paterno: z.string().optional(),
    cli_apellido_materno: z.string().optional(),
    cli_razon_social: z.string().optional(),
    cli_estado: z.string().default("ACTIVO").optional(),
});

在这种情况下,如果cli_Persona_Natural="SI",我需要创建所需的cli_nobres、cli_apellido_matno和cli_apellido_Paterno,有什么 idea 可以这样做吗?谢谢

如果cli_Persona_Natural为"SI",我希望字段是必填字段

推荐答案

您可以使用superRefine方法来指定类似这样的附加约束,也可以在本例中使用discriminatedUnion,最终得到略微更强的类型.

超级精细化方法:

const formSchema = z
  .object({
    cli_rut: z.string(),
    cli_persona_natural: z.enum(["SI", "NO"]),
    cli_nombres: z.string().optional(),
    cli_apellido_paterno: z.string().optional(),
    cli_apellido_materno: z.string().optional(),
    cli_razon_social: z.string().optional(),
    cli_estado: z.string().default("ACTIVO").optional(),
  })
  .superRefine((data, ctx) => {
    if (data.cli_persona_natural === "SI") {
      if (data.cli_nombres === undefined) {
        // I took a best guess at the messages but it's not my native language
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: "El campo nombres es requerido",
        });
      }
      if (data.cli_apellido_paterno === undefined) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: "El campo apellido paterno es requerido",
        });
      }
      if (data.cli_apellido_materno === undefined) {
        ctx.addIssue({
          code: z.ZodIssueCode.custom,
          message: "El campo apellido materno es requerido",
        });
      }
    }
  });

歧视并集方法

import { z } from "zod";

const baseSchema = z.object({
  cli_rut: z.string(),
  cli_razon_social: z.string().optional(),
  cli_estado: z.string().default("ACTIVO").optional(),
});

const personaNaturalSchema = z.object({
  cli_persona_natural: z.literal("SI"),
  cli_nombres: z.string(),
  cli_apellido_paterno: z.string(),
  cli_apellido_materno: z.string(),
});

// Again no clue if this naming makes sense in practice
const personaJuridicaSchema = z.object({
  cli_persona_natural: z.literal("NO"),
  cli_nombres: z.string().optional(),
  cli_apellido_paterno: z.string().optional(),
  cli_apellido_materno: z.string().optional(),
});

const formSchema = z
  .discriminatedUnion("cli_persona_natural", [
    personaNaturalSchema,
    personaJuridicaSchema,
  ])
  .and(baseSchema);

console.log(
  formSchema.safeParse({
    cli_persona_natural: "SI",
    cli_rut: "12345678",
    cli_nombres: "John",
    cli_apellido_paterno: "Steve",
    cli_apellido_materno: "Tessa",
  })
); // success
console.log(
  formSchema.safeParse({
    cli_persona_natural: "NO",
    cli_rut: "12345678",
  })
); // success
console.log(
  formSchema.safeParse({
    cli_persona_natural: "SI",
    cli_rut: "12345678",
  })
); // failure

这种方法对类型有好处.如果判断值cli_persona_natural,则会得到关于其他字段是否必需的类型推断.

Typescript相关问答推荐

替代语法/逻辑以避免TS变量被分配之前使用." "

React重定向参数

带switch 的函数的返回类型的类型缩小

为什么不能使用$EVENT接收字符串数组?

错误TS2403:后续变量声明必须具有相同的类型.变量';CRYPTO';的类型必须是';CRYPATO';,但这里的类型是';CRYPATO';

使用Redux Saga操作通道对操作进行排序不起作用

在类型脚本中创建泛型类型以动态追加属性后缀

在打印脚本中使用泛型扩展抽象类

转换器不需要的类型交集

在类型脚本中将泛型字符串数组转换为字符串字母并集

如果判断空值,则基本类型Gaurd不起作用

对于VUE3,错误XX不存在于从不存在的类型上意味着什么?

如何从抽象类的静态方法创建子类的实例?

有没有什么方法可以使用ProvideState()提供多个削减器作为根减减器

如何填写Partial的一些属性并让类型系统知道它?

如何在TypeScript类成员函数中使用筛选后的keyof this?

如何确定剧作家中给定定位器的值?

如何在 TypeScript 类型定义中简化定义长联合类型

如何确定单元格中的块对 mat-h​​eader-cell 的粘附(粘性)?

根据索引将元组拆分为两个块