'How to create a union type of indexes of a constant array with Typescript?

I have a constant array of strings e.g.

const emojis = ['😄', '😊', '😐', '😕', '😣'] as const

And I want to have a type that contains a union of the indexes of that array e.g.

type emojiIndexes = IndexesOfArray<typeof emojis> // => 0 | 1 | 2 | 3 | 4

So that I don't allow using number and use only the exact number of the indexes in the array

And if the array size e.g.

// changed from this
// const emojis = ['😄', '😊', '😐', '😕', '😣'] as const
// to this 
const emojis = ['😄', '😊', '😐'] as const // removed 2 emojis

Than, IndexesOfArray<typeof emojis> would be 0 | 1 | 2

How can I create IndexesOfArray that would create a union type with the indexes of the constant array?



Solution 1:[1]

You can do this by excluding all empty-array keys from the parameter type, so you end up with a union of just the indices:

type IndexesOfArray<A> = Exclude<keyof A, keyof []>

const emojis = ['?', '?', '?', '?', '?'] as const

type emojiIndexes = IndexesOfArray<typeof emojis> // => '0' | '1' | '2' | '3' | '4'

The indices are strings instead of numbers but that should not cause any issues. If you do want numbers, you could use a recursive conditional type to generate them, but this will cause issues with TypeScript's recursion depth. Alternatively, you can use a slightly hacky hard-coded array and index that to get the numbers:

type ToNum = [0,1,2,3,4,5,6,7] // add as many as necessary

type emojiNumIndexes = ToNum[IndexesOfArray<typeof emojis>] // => 0 | 1 | 2 | 3 | 4

TypeScript playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1