メインコンテンツまでスキップ

オブジェクトからキーの型を生成する

オブジェクトからキーだけ欲しい

あるメッセージが言語ごとに定義されているとします。

ts
const conf = {
en: "Are you sure?",
fr: "Êtes-vous sûr?",
es: "Está seguro?",
ja: "よろしいですか?",
zh: "您确定吗?",
};
ts
const conf = {
en: "Are you sure?",
fr: "Êtes-vous sûr?",
es: "Está seguro?",
ja: "よろしいですか?",
zh: "您确定吗?",
};

内容は確認を促す変哲もないシステムのメッセージです。このオブジェクトを使ってシステムがサポートしている言語の一覧を作ります。次のようなユニオン型が今回の目的です。

ts
type Language = "en" | "fr" | "es" | "ja" | "zh";
ts
type Language = "en" | "fr" | "es" | "ja" | "zh";

typeof

頻出するこのtypeofはJavaScriptのものではなく、TypeScriptのtypeofです。これをオブジェクトに対して使用している例は前のページにあるとおりです。

📄️ オブジェクトから型を生成する

多くの言語では型による構造体、オブジェクトの定義をしてからコーディングが始まりますが、元がJavaScriptであるTypeScriptにはそのような決まりがないことも多々あります。

この例で実行すれば次のような型TypeOfLanguageが生成されるでしょう (型名は便宜的なものです) 。

ts
type TypeOfLanguage = typeof conf;
type TypeOfLanguage = { en: string; fr: string; es: string; ja: string; zh: string; }
ts
type TypeOfLanguage = typeof conf;
type TypeOfLanguage = { en: string; fr: string; es: string; ja: string; zh: string; }

ここまでくればあとは少しです。TypeOfLanguage型のキーだけを型にしてしまいます。

keyof

keyofはオブジェクトの型に使うとそのオブジェクトのキーをユニオン型にして返します。上記のTypeOfLanguage型があれば

ts
type Language = keyof TypeOfLanguage;
type Language = "en" | "fr" | "es" | "ja" | "zh"
ts
type Language = keyof TypeOfLanguage;
type Language = "en" | "fr" | "es" | "ja" | "zh"

となります。

📄️ keyof型演算子

keyofはオブジェクトの型からプロパティ名を型として返す型演算子です。たとえば、nameプロパティを持つ型に対して、keyofを使うと文字列リテラル型の"name"が得られます。

まとめ

見た目が少々いびつですが、次でオブジェクトから希望するキーのユニオン型を生成できます。

ts
type Language = keyof typeof conf;
type Language = "en" | "fr" | "es" | "ja" | "zh"
ts
type Language = keyof typeof conf;
type Language = "en" | "fr" | "es" | "ja" | "zh"

疑問: keyof confじゃダメなんですか?

動作しません。なぜならkeyofは値ではなく (オブジェクトの) 型に対して使用できるからです。一方typeofは値から型を生成するのでこの順番で使用する必要があります。