如何从Record构建Zod字面量数组?解决类型不兼容错误
解决方案
问题根源在于两点:
Object.keys(mapping)返回的是string[],类型精度不足,导致生成的Zod字面量类型模糊z.union要求传入至少两个Zod类型组成的元组,但map返回的普通数组无法被TypeScript推断为符合要求的元组
修正步骤及完整代码
- 让
mapping的类型更精确:去掉Record<number, string>的显式定义,用as const让TypeScript推断出具体的键值对类型 - 提取
mapping的键类型,将Object.keys结果断言为该类型数组,确保类型准确 - 将生成的Zod字面量数组断言为元组,满足
z.union的参数要求
const mapping = { 0: 'walking', 1: 'jogging', 2: 'running' } as const; type MappingKey = keyof typeof mapping; // 将数组断言为元组,满足z.union的参数要求 const keyZodLiterals = (Object.keys(mapping) as MappingKey[]).map(key => z.literal(key)) as [z.ZodLiteral<0>, z.ZodLiteral<1>, z.ZodLiteral<2>]; const modelOutput = modelOutputSchema.parse( z .array(z.union(keyZodLiterals)) .parse(JSON.parse(data)) .map((el, index) => ({ timestamp: rawData[index].Timestamp, label: mapping[el], })), );
通用化写法(无需手动指定元组元素)
如果不想手动写具体的元组类型,可以用类型工具自动推断元组:
const mapping = { 0: 'walking', 1: 'jogging', 2: 'running' } as const; type MappingKey = keyof typeof mapping; // 类型工具:将数组转为至少包含一个元素的元组 type NonEmptyTuple<T> = [T, ...T[]]; const keyZodLiterals = (Object.keys(mapping) as MappingKey[]).map(key => z.literal(key)) as NonEmptyTuple<z.ZodLiteral<MappingKey>>; const modelOutput = modelOutputSchema.parse( z .array(z.union(keyZodLiterals)) .parse(JSON.parse(data)) .map((el, index) => ({ timestamp: rawData[index].Timestamp, label: mapping[el], })), );
内容的提问来源于stack exchange,提问作者Rodrigo
相关产品推荐
相关产品推荐

