如何基于as const定义的对象创建Zod枚举类型?
我有一个自动生成的对象:
export const ReportDimensions = { CHANNELS: 'CHANNELS', DAY: 'DAY', DOW: 'DOW', MONTH: 'MONTH', WEEK: 'WEEK' } as const;
我希望使用Zod创建仅允许该对象值的枚举,即允许["MONTH","WEEK","DOW", "DAY", "CHANNELS"]这些值。尝试使用z.enum(Object.keys(ReportDimensions))时出现如下报错:
No overload matches this call.
Overload 1 of 2, '(values: readonly [string, ...string[]], params?: RawCreateParams): ZodEnum<[string, ...string[]]>', gave the following error.
Argument of type 'string[]' is not assignable to parameter of type 'readonly [string, ...string[]]'.
Source provides no match for required element at position 0 in target.
Overload 2 of 2, '(values: [string, ...string[]], params?: RawCreateParams): ZodEnum<[string, ...string[]]>', gave the following error.
Argument of type 'string[]' is not assignable to parameter of type '[string, ...string[]]'.
Source provides no match for required element at position 0 in target.ts(2769)
原因分析
Object.keys()返回的类型是string[],而Zod的z.enum()要求传入非空的只读字符串字面量数组类型(readonly [string, ...string[]])。TypeScript无法推断Object.keys()的结果是确定的非空数组,也无法保留具体的字符串字面量类型,因此触发类型报错。
正确实现方式
你的对象已经使用as const锁定了字面量类型,可以通过以下两种方式实现需求:
方式一:提取对象值并断言为字面量数组
import { z } from "zod"; export const ReportDimensions = { CHANNELS: 'CHANNELS', DAY: 'DAY', DOW: 'DOW', MONTH: 'MONTH', WEEK: 'WEEK' } as const; // 提取对象值并断言为字面量数组 const dimensionValues = Object.values(ReportDimensions) as [typeof ReportDimensions[keyof typeof ReportDimensions]]; // 创建Zod枚举 const ReportDimensionSchema = z.enum(dimensionValues); // 导出对应的TypeScript类型 type ReportDimension = z.infer<typeof ReportDimensionSchema>;
方式二:使用z.nativeEnum(更简洁)
由于你的对象键值完全一致,直接使用z.nativeEnum可以自动解析常量对象的键值作为枚举选项:
import { z } from "zod"; export const ReportDimensions = { CHANNELS: 'CHANNELS', DAY: 'DAY', DOW: 'DOW', MONTH: 'MONTH', WEEK: 'WEEK' } as const; // 创建Zod枚举 const ReportDimensionSchema = z.nativeEnum(ReportDimensions); // 导出对应的TypeScript类型 type ReportDimension = z.infer<typeof ReportDimensionSchema>;
验证效果
两种方式都能严格限制枚举值范围:
- 合法值:
ReportDimensionSchema.parse("MONTH")→ 解析成功 - 非法值:
ReportDimensionSchema.parse("YEAR")→ 抛出Zod验证错误
内容的提问来源于stack exchange,提问作者Crocsx

