如何用Zod验证对象中仅存在指定属性之一?
Zod实现「必须且仅存在指定属性之一」的验证方案
直接给你可行的实现方式,同时解答关于Enum的疑问:
1. 核心方案:z.union + 单属性对象Schema
通过合并三个仅包含单个必填属性的对象Schema,就能实现「必须存在且仅存在三个属性之一」的验证逻辑:
import { z } from "zod"; // 替换z.any()为你实际需要的属性类型(比如z.string()、z.number()等) const ResultsSchema = z.union([ z.object({ resultType1: z.any() }), z.object({ resultType2: z.any() }), z.object({ resultType3: z.any() }), ]); // 验证示例 ResultsSchema.parse({ resultType1: "success" }); // ✅ 通过 ResultsSchema.parse({ resultType2: 42 }); // ✅ 通过 ResultsSchema.parse({ resultType3: { data: [] } }); // ✅ 通过 ResultsSchema.parse({}); // ❌ 失败:无指定属性 ResultsSchema.parse({ resultType1: "foo", resultType2: "bar" }); // ❌ 失败:多属性共存
如果需要严格禁止对象包含额外属性,给每个对象Schema加上.strict()即可:
const StrictResultsSchema = z.union([ z.object({ resultType1: z.any() }).strict(), z.object({ resultType2: z.any() }).strict(), z.object({ resultType3: z.any() }).strict(), ]); StrictResultsSchema.parse({ resultType1: "foo", extraKey: "baz" }); // ❌ 失败:存在额外属性
2. 关于Enum的使用
Enum可以用来约束属性的取值范围,但无法直接实现「仅存在一个属性」的规则。不过你可以把Enum和上面的方案结合,同时实现属性存在规则和取值约束:
import { z } from "zod"; // 定义枚举 enum ResultEnum { TYPE1 = "RESULT_TYPE_1", TYPE2 = "RESULT_TYPE_2", TYPE3 = "RESULT_TYPE_3", } const ResultsWithEnumSchema = z.union([ z.object({ resultType1: z.nativeEnum(ResultEnum) }), z.object({ resultType2: z.nativeEnum(ResultEnum) }), z.object({ resultType3: z.nativeEnum(ResultEnum) }), ]); // 验证示例 ResultsWithEnumSchema.parse({ resultType1: ResultEnum.TYPE1 }); // ✅ 通过 ResultsWithEnumSchema.parse({ resultType2: "INVALID_VALUE" }); // ❌ 失败:取值不在枚举内
补充说明
你提到的required属性不适用这里——它只能确保某个属性必须存在,但无法阻止多个指定属性同时出现,所以达不到「仅存在一个」的要求。
内容的提问来源于stack exchange,提问作者physicsboy
相关产品推荐
相关产品推荐

