如何使用Zod discriminatedUnion结合枚举鉴别器,无需列出所有枚举值?
解决Zod基于枚举鉴别字段的条件验证问题
针对你遇到的场景——当枚举字段为VAL1时otherField必填字符串,为其他枚举值时otherField必须为undefined,无需逐个枚举所有值的解决方案如下:
方法一:使用z.union配合refine过滤枚举值
这种方式保留分支式结构,同时避免手动列出所有枚举值:
import { z } from "zod"; import { MyEnum } from "@prisma/client"; // 导入Prisma生成的枚举 const schema = z.union([ // 分支1:鉴别字段为VAL1时,otherField必填字符串 z.object({ discriminatorField: z.literal(MyEnum.VAL1), otherField: z.string() }), // 分支2:鉴别字段为枚举中除VAL1外的其他值,otherField必须为undefined z.object({ discriminatorField: z.nativeEnum(MyEnum).refine(val => val !== MyEnum.VAL1), otherField: z.undefined() }) ]);
为什么可行?
z.nativeEnum(MyEnum).refine(...)会过滤掉VAL1,确保两个分支的鉴别值完全互斥,解决了直接用nativeEnum导致的重叠报错问题。Zod会按顺序匹配分支,优先校验第一个分支,符合条件则直接通过,否则进入第二个分支。
方法二:使用单对象加refine全局校验
如果觉得分支结构冗余,可以直接在单个对象Schema后添加refine做条件校验:
import { z } from "zod"; import { MyEnum } from "@prisma/client"; const schema = z.object({ discriminatorField: z.nativeEnum(MyEnum), otherField: z.string().optional() }).refine(data => { // 核心条件判断 return data.discriminatorField === MyEnum.VAL1 ? typeof data.otherField === "string" : data.otherField === undefined; }, { // 自定义错误提示 message: "鉴别字段为VAL1时otherField必须是字符串,其他情况必须为undefined" });
这种方式更简洁,适合逻辑不复杂的场景,错误提示也可根据需求自定义。
内容的提问来源于stack exchange,提问作者Adrian Schweizer
相关产品推荐
相关产品推荐

