如何使用 Typescript 创建常量数组索引的联合类型?

Ven*_*sky 7 typescript typescript-generics

我有一个常量字符串数组,例如

const emojis = ['', '', '', '', ''] as const
Run Code Online (Sandbox Code Playgroud)

我想要一个包含该数组索引的并集的类型,例如

type emojiIndexes = IndexesOfArray<typeof emojis> // => 0 | 1 | 2 | 3 | 4
Run Code Online (Sandbox Code Playgroud)

所以我不允许使用number并且仅使用数组中索引的确切数量

如果数组大小例如

// changed from this
// const emojis = ['', '', '', '', ''] as const
// to this 
const emojis = ['', '', ''] as const // removed 2 emojis
Run Code Online (Sandbox Code Playgroud)

比,IndexesOfArray<typeof emojis>会是0 | 1 | 2

我怎样才能创建IndexesOfArray一个带有常量数组索引的联合类型?

kay*_*ya3 4

这是一个解决方案:(游乐场链接

type TupleIndices<A extends any[]>
    = A extends [any, ...infer T]
    ? TupleIndices<T> | T['length']
    : never
Run Code Online (Sandbox Code Playgroud)

例子:

type Foo = ['foo', 'bar', 'baz', 'qux', 'quz']

// 0 | 4 | 3 | 2 | 1
type FooIndices = TupleIndices<Foo>
Run Code Online (Sandbox Code Playgroud)

由于该解决方案是递归的,因此对于中等长度的元组它将失败。如果您需要它适用于较长的元组,您可以尝试尾递归版本:(Playground Link

type TupleIndices<A extends any[], Acc = never>
    = A extends [any, ...infer T]
    ? TupleIndices<T, Acc | T['length']>
    : Acc
Run Code Online (Sandbox Code Playgroud)

用法是一样的。

  • 但由于递归限制,这对于超过 23 个元素会失败。 (2认同)