【问题标题】:Get type literal of tuple value in array of tuples获取元组数组中元组值的类型字面量
【发布时间】:2023-01-18 02:10:14
【问题描述】:

给定数组

const arr = [[0, 'foo'], [1, 'bar']] as const;

我需要值是具体的文字值,而不是string'foo' | 'bar'

const value = get(arr, 0); // value type: 'foo'

我最好的尝试是

type Entry<K, V> = readonly [K, V];
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)!;
}

const arr = [[0, 'foo'], [1, 'bar']] as const;
const val = get(arr, 0);

但它导致 val 类型为 'foo' | 'bar'

【问题讨论】:

  • this approach 是否满足您的需求?如果是这样,我可以写一个答案来解释;如果没有,我错过了什么?
  • @jcalz 是的,它很完美,非常感谢你:)

标签: arrays typescript tuples


【解决方案1】:

我建议编写 get(),以便 generic 类型参数和函数参数之间的关系尽可能简单明了,以获得正确的推理。因此,与其让 arr 成为与两个独立类型参数相关的类型,不如让 arr 成为仅与一个类型参数相关的一种简单方式,并让 id 与另一个。

例如:

function get<T extends readonly [PropertyKey, string], K extends T[0]>(
    arr: readonly T[], id: K
): Extract<T, readonly [K, any]>[1] {
    return new Map(arr).get(id)!;
}

这里arr 的类型是一个(可能是readonly)类型为T 的元素数组,它是constrained 到(可能是readonly)条目元组类型。因此,如果您传入 get([[k1, v1], [k2, v2], [k3, v3]], ...),则应将 T 推断为等同于 the union type [typeof k1, typeof v1] | [typeof k2, typeof v2] | [typeof k3, typeof v3]id 的类型是 K,它被限制为元组类型的 T 联合中的键之一(您可以通过 indexing into T 获得,索引为 0)。

为了确定返回类型,我们需要取联合TExtract其键对应于K的联合成员。一旦我们这样做了,我们通过使用索引1对其进行索引,从该条目中获取值类型。

让我们测试一下:

const val = get(arr, 0);
// const val: "foo"
const val2 = get(arr, 1);
// const val2: "bar"

看起来挺好的。

Playground link to code

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 2013-10-28
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    相关资源
    最近更新 更多