You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Zod基于枚举属性而非值校验?原因与解决方法

问题场景

我正在使用Zod Schema校验一个包含枚举字段的对象,代码如下:

enum Colour {
    red = 'Red',
    blue = 'Blue',
}

const schema = z.object({
    colour: z.nativeEnum(Colour),
});

从API获取的颜色输入值为'red'或'blue',希望用上述Schema校验,但当前z.nativeEnum校验的是枚举中的大写值(如'Red')而非枚举属性(如'red'):

enum Colour {
    red = 'Red',
    blue = 'Blue',
}

const schema = z.object({
    colour: z.nativeEnum(Colour),
});

const rawInput1 = {
    colour: 'red' // 应被判定为有效
};
const parsedInput1 = schema.parse(rawInput1); // 校验失败

const rawInput2 = {
    colour: 'Red' // 应被判定为无效
};
const parsedInput2 = schema.parse(rawInput2); // 校验通过

我需要让Zod基于枚举属性而非值进行校验,并且解析对象后,要用colour变量通过枚举索引获取其字符串值(即Colour[parsedInput1.colour]),若colour为字符串值则无法实现该操作。


问题原因

z.nativeEnum(Colour)的核心逻辑是校验输入值是否属于枚举的值集合(即'Red'、'Blue')。TypeScript的字符串枚举编译后会生成包含双向映射的对象(键→值、值→键),但Zod的nativeEnum方法默认以枚举的值作为校验范围,因此只会允许枚举定义中=右侧的内容通过校验。


解决方案

方法1:提取枚举键创建Zod枚举校验器

通过Object.keys提取枚举的键数组,再用z.enum创建校验器,直接校验输入是否为枚举的合法键:

enum Colour {
    red = 'Red',
    blue = 'Blue',
}

// 提取枚举的键并断言为合法键类型
const ColourKeys = Object.keys(Colour) as Array<keyof typeof Colour>;

const schema = z.object({
    colour: z.enum(ColourKeys),
});

// 测试
const rawInput1 = { colour: 'red' };
const parsedInput1 = schema.parse(rawInput1); // 校验通过
console.log(Colour[parsedInput1.colour]); // 输出 'Red'

const rawInput2 = { colour: 'Red' };
schema.parse(rawInput2); // 校验失败,符合预期

方法2:使用refine自定义校验逻辑

如果需要更灵活的校验,可以用z.string().refine来检查输入是否是枚举的合法键:

enum Colour {
    red = 'Red',
    blue = 'Blue',
}

const schema = z.object({
    colour: z.string().refine(
        val => Object.keys(Colour).includes(val),
        { message: 'colour必须是red或blue' }
    ),
});

// 测试效果和方法1一致

内容的提问来源于stack exchange,提问作者Lemour

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 02:32:27