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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:30:16