👀

インデックスアクセス型【個人学習まとめ】

に公開

インデックスアクセス型

学習中にインデックスアクセス型で躓いたので、調べたことをまとめました。

今回、躓いたコードは次のようなコードです。

const STATUS = ["todo", "working", "done"] as const;
type Status = (typeof STATUS)[number];

普段から TypeScript を触れている型であれば、このコードのtype Status = (typeof STATUS)[number];部分はどんなことをしているコードがパッと判断できる方が多いと思います。
もし判断が付かなくてもこの記事で学習しましょう!!!

type xxx = (typeof ○○○)[number]は何をしているのか

結論からいうとこれは**「配列内の要素の型を取り出す」**ということをやっています。

少しずつ確認してみましょう。

as const

本題に入る前に一か所だけ確認します。
これはconstアサーションと呼ばれ、変数が読み取り専用であることを示します。
これにより、配列を読み取り専用のタプルとして扱います。
const アサーションの記事

typeof arr[]

typeof演算子は JavaScirpt と TypeScript でそれぞれ違いがあります。
JavaScript は指定した値の型を絞り込むTypeScript では変数から型を抽出し、型情報を返却するという違いです。以前の記事で紹介しました

今回は TypeScript のtypeof演算子が使われています。
分かりやすいように[number]部分を取り除いて、型情報が返却されているか見てみます。

const STATUS = ["todo", "working", "done"] as const;
+ type Status_1 = typeof STATUS;
+ type Status_2 = (typeof STATUS)[number];
- type Status = (typeof STATUS)[number];

では、型Status_1の中身はどうなっているのかというと・・・

type Status_1 = readonly ["todo", "working", "done"];

となり、STATUS配列全体の型を取得しています。
ではStatus_2はどうなっているでしょうか。

type Status_2 = "todo" | "working" | "done";

ユニオン型となっています。

初めに書いたように、type xxx = (typeof ○○○)[number]では**「配列内の要素の型を取り出す」**ということをやっています。
つまり分解してみると

STATUS[0]"todo"STATUS[1]"working"STATUS[2]"done"

となります。
これらをすべて集める・・・

"todo" | "working" | "done";

というユニオン型になります。Status_2の中身と一致していますね!

まとめ

あらためて最初のコードを見てみましょう。

const STATUS = ["todo", "working", "done"] as const;
type Status = (typeof STATUS)[number];

ここまできたらこのコードでどんなことをやっているか理解できますね!

構文 意味
typeof arr 配列全体の型
typeof arr[number] 配列の要素型(Union)
  • [number] は配列の要素型を取り出すためのインデックスアクセス型
  • as const を使うことで、文字列リテラル型として扱える

おまけ

インデックスアクセス型を利用することによって、将来的に新たなステータスの型を追加した場合、STATUSにその要素を追加するだけで型Statusに反映されるようになります!
例) reviewを追加

const STATUS = ["todo", "working", "done", "review"] as const;
type Status = (typeof STATUS)[number];
// → "todo" | "working" | "done" | "review"

Discussion