z.enum相关类型问题:typeof a不符合预期的原因及修复方法
问题解析与修复方案
为什么类型不符合预期?
你定义的optionsToEnum函数泛型T被TypeScript推断为"a" | "b",因为entries的类型是ReadonlyArray<Readonly<[T, { label: string }]>>,这里的ReadonlyArray是数组类型而非元组类型,所以map返回的结果是T[](即("a" | "b")[])。解构后firstValue是T,restValues是T[],最终返回的类型就变成了[T, ...T[]],也就是["a" | "b", ...("a" | "b")[]],无法保留原元组的具体元素顺序和类型。
修复方案
要让函数保留原元组的具体类型,需要将泛型约束为元组类型,而不是数组类型。修改函数的泛型定义,让它接收整个元组作为泛型参数,然后提取其中的value部分:
import { z } from 'zod' const options = [ ["a", { label: "A" }], ["b", { label: "B" }], ] as const // 泛型T约束为包含[value: unknown, { label: string }]元素的元组 export function optionsToEnum<T extends ReadonlyArray<Readonly<[value: unknown, { label: string }]>>>( entries: T ): { [K in keyof T]: T[K][0] } { return entries.map(([value]) => value) as { [K in keyof T]: T[K][0] } } const a = optionsToEnum(options) // typeof a 现在是 ["a", "b"] z.enum(a) // 正常工作
或者更简洁的写法,利用infer提取元组元素的value类型:
export function optionsToEnum<T extends Readonly<[unknown, { label: string }]>[]>( entries: readonly [...T] ): T extends readonly [infer V1, ...infer Rest] ? [V1[0], ...{ [K in keyof Rest]: Rest[K][0] }] : never { return entries.map(([value]) => value) as any }
这两种写法都能让TypeScript正确推断出a的类型是["a", "b"],因为泛型捕获了原元组的具体结构,而不是只捕获元素的联合类型。
内容的提问来源于stack exchange,提问作者Pavel Perevezencev
相关产品推荐
相关产品推荐

