如何获取元组数组中指定元组的具体字面量类型?
如何从const断言的键值对数组中获取对应字面量类型的值
你遇到的问题我太懂了——就是想从用as const固定类型的键值对数组里,根据键拿到精确的字面量类型值,而不是所有值的联合类型对吧?咱们先看看你原来的代码为什么没达到预期,再一步步改好它。
问题出在哪?
你原来的GetType类型定义和函数约束都有点太宽泛了:
type GetType<A extends readonly Entry<any, any>[], K> = A extends readonly Entry<K, infer V>[] ? V : never; function get<K extends PropertyKey, V extends string>(arr: readonly Entry<K, V>[], id: K): GetType<typeof arr, K> { return new Map(arr).get(id)!; }
这里的核心问题是:TypeScript会把整个数组当成Entry<K, V>[]来匹配,这时候V会被推断成数组里所有值的联合类型(也就是'foo' | 'bar'),因为它认为数组里的每个条目都符合Entry<K, V>,自然会把所有值合并成一个集合。同时函数的泛型约束也没保留住数组里每个键值对的精确关联信息。
解决方案:精准匹配键对应的条目类型
我们需要调整两个关键部分:一是GetType的逻辑,让它从数组元素里筛选出键匹配的那个条目,再提取值类型;二是函数的泛型约束,让TypeScript能保留数组的具体字面量类型细节。
1. 修正GetType类型
用Extract工具类型精准筛选数组中键匹配的条目,再通过条件类型提取对应的值类型:
type Entry<K, V> = readonly [K, V]; // 从数组A中提取键为K的条目,再取出它的值类型 type GetType<A extends readonly Entry<any, any>[], K> = Extract<A[number], Entry<K, any>> extends Entry<any, infer V> ? V : never;
这里A[number]会得到数组所有元素的联合类型,Extract会从中筛选出第一个元素是K的条目,最后通过条件类型推断出这个条目的值类型V。
2. 修正get函数的泛型约束
把函数改成泛型,让数组的类型是具体的A(而非宽泛的Entry<K, V>[]),同时让K约束为数组中所有键的类型,这样TypeScript就能精准追踪每个键对应的值类型:
function get<A extends readonly Entry<any, any>[], K extends A[number][0]>( arr: A, id: K ): GetType<A, K> { // 非空断言是因为我们确定K存在于数组中 return new Map(arr).get(id)!; }
测试效果
现在再调用函数,就能得到你想要的精确字面量类型了:
const arr = [[0, 'foo'], [1, 'bar']] as const; const val = get(arr, 0); // 类型是'foo',完美! const val2 = get(arr, 1); // 类型是'bar'
这样就完全满足需求了——传入不同的键,返回值的类型会自动对应到具体的字面量,而不是模糊的联合类型。
内容的提问来源于stack exchange,提问作者Yiin
相关产品推荐
相关产品推荐

