有一种简单的方法可以获得您想要的行为,假设当列表中不包括'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
字段.只要其他数据没有出现在您要解析的值中,就不会有问题.