🔑

TypeScriptのkeyofを知ろう

に公開

概要

別記事を書くにあたりkeyofを理解しようの会

keyofとは

型を受け取り、そのキーを集合させた型を定義するもの。
参考: https://www.typescriptlang.org/docs/handbook/2/keyof-types.html

とはいえ分かりづらいと思うので例を書くとこんな感じ。

const hoge: Hoge = { name: "ほげ太郎", message: "こんにちは、ほげ太郎です。" };
type Hoge = { name: string; message: string };
type Fuga = keyof Hoge; // "name" | "message" というリテラル型が入る

リテラル型の説明はこちら。

説明の通りkeyofは型を受け取るので値を用いる場合は typeof を使用する。
上記のHogeがないバージョンだと、たまにコードでつまづく一因となる keyof typeof になる。

const hoge = { name: "ほげ太郎", message: "こんにちは、ほげ太郎です。" };
type Fuga = keyof typeof hoge; // "name" | "message" というリテラル型が入る

ちなみに、 string[] みたいな配列に対しての keyof string[]number である。
(そんなに使わないかもだけど)keyof string はnumberに加えてJavaScriptのStringのプロパティとメソッドも格納されるっぽい。

ちなみに

さっきのHogeは以下のように定義することもできるが

const hoge: Hoge = { name: "ほげ太郎", message: "こんにちは、ほげ太郎です。" };
type Hoge = { [k: string]: string };
type Fuga = keyof Hoge;

その場合のFugaはstring | numberとなる。
これはJavaScriptの仕様上object[0]とアクセスしてもobject["0"]とアクセスしても同じ感じになるのでnumberが付いてきてしまうっぽいとのこと。

Discussion