TypeScriptで定数配列のインデックスのユニオン型を作成する方法は?
私は文字列の定数配列を持っています。例えば
const emojis = ['😄', '😊', '😐', '😕', '😣'] as const
そして、私はその配列のインデックスの共用体を含む型を持ちたい、例えば
type emojiIndexes = IndexesOfArray<typeof emojis> // => 0 | 1 | 2 | 3 | 4
そのため、number の使用を許可せず、配列内のインデックスの正確な数だけを使用します
そして、配列のサイズが例えば
// changed from this
// const emojis = ['😄', '😊', '😐', '😕', '😣'] as const
// to this
const emojis = ['😄', '😊', '😐'] as const // removed 2 emojis
すると、IndexesOfArray<typeof emojis> は 0 | 1 | 2 になります
定数配列のインデックスを持つユニオン型を作成する IndexesOfArray をどのように作成できますか?
回答 #1
こちらが解決策です:(Playgroundリンク)
type TupleIndices<A extends any[]>
= A extends [any, ...infer T]
? TupleIndices<T> | T['length']
: never
例:
type Foo = ['foo', 'bar', 'baz', 'qux', 'quz']
// 0 | 4 | 3 | 2 | 1
type FooIndices = TupleIndices<Foo>
この解法は再帰的なので、やや長いタプルでは失敗します。もし長いタプルでも動作させたい場合は、末尾再帰版を試すことができます:(Playground リンク)
type TupleIndices<A extends any[], Acc = never>
= A extends [any, ...infer T]
? TupleIndices<T, Acc | T['length']>
: Acc
使い方は同じです。
回答 #2
これは、空の配列キーをすべてパラメーター型から除外することで行うことができるので、結果としてインデックスだけの共用体になります:
type IndexesOfArray<A> = Exclude<keyof A, keyof []>
const emojis = ['😄', '😊', '😐', '😕', '😣'] as const
type emojiIndexes = IndexesOfArray<typeof emojis> // => '0' | '1' | '2' | '3' | '4'
インデックスは数字ではなく文字列ですが、これは問題を引き起こすべきではありません。もし数字が必要であれば、再帰的な条件付き型を使って生成することもできますが、これによりTypeScriptの再帰の深さに問題が生じます。あるいは、少しハック的なハードコーディングされた配列を使い、それにインデックスを付けて数字を取得することもできます。
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 プレイグラウンド
