【问题标题】:Is there a way to get keys of tuple as numbers?有没有办法将元组的键作为数字?
【发布时间】:2020-02-22 02:04:04
【问题描述】:

假设我有一些元组类型:

type SomeTuple = ["a", "b", "c"];

现在我想以某种方式将它的键作为数字:

type SomeTupleKeys<T = SomeTuple> = 0 | 1 | 2;

我尝试使用keyof SomeTuple,但它返回

号码 | "0" | "1" | "2" | “长度” | "toString" | "toLocaleString" | “流行” | “推” | “连接” | “加入” | “反向” | “转移” | “切片” | “排序” | “拼接” | “不换档” | “索引” | ... 14 更多... | “价值观”

我也尝试过更复杂的解决方案

type B = (SomeTuple extends infer T ? { [K in keyof T]: K extends keyof T ? K : never } : never)[number];

但是这个给了我字符串:

"0" | "1" | “2”

有没有办法在不进行硬编码的情况下获取数字?

Demo

【问题讨论】:

  • 为什么需要这个? SomeTuple[1] 和SomeTuple["1"] 挑出同一个元素;是否有一些用例需要数字而不是字符串?
  • @jcalz, { [key in TupleKeys]: { length: key } } - 我在length 属性中遇到了字符串问题...
  • “没有硬编码任何东西”?可能没有任何支持的方式。你可以使用递归类型来增长一个元组直到它的长度匹配,但这比你索引到的像[0,1,2,3,4,5,6,7,8,9,10,11,12,...] 这样的大元组更密集。
  • @jcalz,我其实不知道怎么做递归类型...
  • 查看here获取相关答案,其中映射元组的字符串键"0"、"1"、...被转换为数字类型以使它们与元组@相当987654335@ 数字财产。但我仍然会称其为 hacky,因此这里也没有硬编码的简单解决方案。

标签: typescript generics tuples


【解决方案1】:

这可以通过recursive conditional types(在 Typescript 4.1 中添加)来完成:

type TupleKeys<T extends ReadonlyArray<unknown>, Keys extends ReadonlyArray<number> = []> =
    T extends [infer _, ... infer R]
        ? TupleKeys<R, [R['length'], ...Keys]>
        : Keys[number];

type SomeTuple = ["a", "b", "c"];
type SomeTupleKeys = TupleKeys<SomeTuple>; // 0 | 2 | 1

Playground


另一个更简单的解决方案(使用较旧的打字稿版本):

type TupleKeys<T extends Array<any>> = Exclude<Partial<T>['length'], T['length']>;

type SomeTuple = ["a", "b", "c"];
type SomeTupleKeys = TupleKeys<SomeTuple>; // 0 | 1 | 2

这里,通过使用Partial我们得到长度为0或1或2或3的元组的并集,然后我们排除3(原始元组的长度)

Playground

【讨论】:

  • 很酷,除了它们都与可选元素一起工作时很奇怪。顺便说一句,我会在单独的答案中发布它。
  • 一个更多选项(保留可选索引):type TupleKeys&lt;T extends Array&lt;any&gt;&gt; = Exclude&lt;Partial&lt;T&gt;['length'], Required&lt;T&gt;['length']&gt;;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-07
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
相关资源
最近更新 更多