我有一个带有数组字段和字符串字段的Zod验证模式:

const zodSchema = z.object({
  goals: z.array(z.string()).nonempty("At least one goal is required"),
  goals_other: z.string(),
});

如果goals数组包含字符串"Other",如何才能使goals_other字段为必填字段?

我try 了如下所示的优化函数,但不起作用

const zodSchema = z
  .object({
    goals: z.array(z.string()).nonempty("At least one goal is required"),
    goals_other: z.string(),
  })
  .refine((data) => (data.goals.includes("Other") ? true : false), {
    message: "Required, please specify other goals",
    path: ["goals_other"],
  });

如有任何帮助,我们不胜感激!

推荐答案

有一种简单的方法可以获得您想要的行为,假设当列表中不包括'Other'时,如果goals_other字段中存在坏数据,您可以接受模式无法解析.我将首先展示这种方法:

import { z } from "zod";

const zodSchema = z
  .object({
    goals: z.array(z.string()).nonempty("At least one goal is required"),
    goals_other: z.string().optional() // optional to avoid failing when it's missing
  })
  .superRefine(({ goals, goals_other }, ctx) => {
    // Here we add the extra check to assert the field exists when
    // the "Other" goal is present.
    if (goals.includes("Other") && goals_other === undefined) {
      ctx.addIssue({
        code: "custom",
        message: "Required, please specify other goals",
        path: ["goals_other"]
      });
    }
  });

console.log(zodSchema.safeParse({
  goals: ['test'],
})); // success
console.log(zodSchema.safeParse({
  goals: ['Other'],
})); // failure
console.log(zodSchema.safeParse({
  goals: ['Other'],
  goals_other: 11,
})); // failure (because goals_other is not a string)
console.log(zodSchema.safeParse({
  goals: ['Other'],
  goals_other: 'test',
})); // success

但国际海事组织对此存在一个问题:

zodSchema.safeParse({
  goals: ['test'],
  goals_other: 11,
}); // Failure

这种解析try 是失败的,因为goals_other字段应该是string | undefined,而它得到了一个数字.如果您真的不关心goals_other字段,除非您的目标列表中有"Other"个目标,那么您真正想要的是忽略该字段,直到找到另一个字符串,然后进行验证.

const zodSchema = z
  .object({
    goals: z.array(z.string()).nonempty("At least one goal is required"),
    goals_other: z.unknown(),
  })
  .superRefine(({ goals, goals_other }, ctx) => {
    if (goals.includes("Other")) {
      if (goals_other === undefined) {
        ctx.addIssue({
          code: "custom",
          message: "Required, please specify other goals",
          path: ["goals_other"]
        });
      } else if (typeof goals_other !== 'string') {
        ctx.addIssue({
          code: 'custom',
          message: 'expected a string',
          path: ['goals_other'],
        });
      }
    }
  });

该模式可以正确解析,但它不会优化输出类型.other_goals将具有类型unknown,这在某种程度上没有帮助.您可以使用transform中的类型断言来解决这个问题,但这也让人感觉有点尴尬.当"Other"不存在时,最好继续第一个模式,并接受您实际上并没有忽略goals_other字段.只要其他数据没有出现在您要解析的值中,就不会有问题.

Reactjs相关问答推荐

react-hook-form问题:为什么getValues不返回大多数当前值?

404使用GitHub操作部署Next.js应用程序时出错

将cy.get()与动态类名一起使用?

使用useReducer时,props 未从父级传递给子或孙级

React,React Router,Joy UI:如何在导航离开和返回后禁用snackbar重新出现?

无法找出状态正在被更改的位置

错误:操作必须是普通对象.使用自定义中间件进行异步操作. Redux/工具包

无法通过 fetch 获取数据到上下文中

我无法通过 useContext 显示值

如何在一个 Next.js 项目中使用两种布局?

Spring Boot + React + MySQL应用的架构层面有哪些?

当我使用 Firebase Auth 在 React 中刷新主页时显示登录页面

Formik onChange() 字段挂钩覆盖显示值和 Select 机制

Select 项目后 Select HeadlessUI 组合框中的所有文本?

我正在通过 API(有效)从 MongoDB 传递数据.可视化但我不断收到此 TypeError: Cannot convert undefined or null to object

react-admin useGetIdentity 只返回全名,id 未定义 头像未定义

如果 URL 已随功能组件更改,则取消刷新

React 检测哪些 props 在 useEffect 触发器上发生了变化

为什么我在运行一些 npm react 命令时会收到这些警告?

如何判断对话框组件是否位于对话框之上?