【入門編】 keyof typeofの組み合わせパターン – TypeScript実践ガイド

こんにちは!フロントエンド・アーキテクチャの現場を渡り歩いているチーフの私です。

TypeScriptを書き始めたばかりの頃って、次から次へと現れる見慣れない記号やイディオムに圧倒されちゃいますよね。「`keyof`? `typeof`? なんだか呪文みたい……」と、エディタを開いたままフリーズしてしまった経験、あなたにもありませんか?

大丈夫ですよ、安心してください。
今日は、実務の現場でも「これがないと生きていけない」くらいヘビーローテーションする`keyof typeof`という最強の組み合わせパターンについて、身近な例えを交えながら、とことん優しく解きほぐしていきますね。

—

1. まずは「身の回りの道具箱」でイメージしてみよう

TypeScriptの型(Type)の世界に入る前に、少しだけ現実世界を想像してみてください。

あなたの机の上に、文房具が入った「お道具箱」があるとします。
そのお道具箱の中身はこんな感じです。

  • `red`: 赤色ペン
  • `blue`: 青色ペン
  • `black`: 黒色ペン

誰かに「このお道具箱にあるペンの『名前(キー)』だけを全部教えて!」と言われたら、あなたは「赤、青、黒だよ」と答えますよね。

プログラミングの世界でもまったく同じです。
JavaScriptのオブジェクトとして用意した「お道具箱」のデータから、「そこにどんな名前(キー)が入っているのか」のリスト(ユニオン型)をTypeScriptに自動で作ってもらう。これが、今回お伝えする `keyof typeof` の正体です。

—

2. 登場人物を個別に見てみよう

`keyof typeof` という呪文は、実は2つの強力な機能がタッグを組んだものです。それぞれが何をしているのか、バラバラに見てみましょう。

その①:`typeof` = 「実物から設計図をこっそりパクる」

普通、TypeScriptの「型」を作るには、`type User = { name: string }` のように、わざわざ新しく設計図を書く必要がありますよね。

でも、すでにJavaScript側で完璧なオブジェクト(実物)がある場合、「この実物と同じ形の型を自動で作ってよ!」と言えるのが `typeof` です。

// お道具箱(JavaScriptのオブジェクト)の実物
const penBox = {
red: “赤色ペン”,
blue: “青色ペン”,
black: “黒色ペン”,
};

// typeofをつけると、このオブジェクトの「構造」がそのまま型になる!
type PenBoxType = typeof penBox;
/
自動で作られる型:
{
red: string;
blue: string;
black: string;
}
/

「わざわざ同じ型を二重に書くのめんどくさいな……」という現場のズボラ心(効率化の心ですね!)を救ってくれるのが `typeof` なのです。

その②:`type of` ではないよ! `keyof` = 「キー(見出し)だけを抜き出す」

次に `keyof` です。これは、オブジェクトの型から、プロパティ名(キー)だけを抜き出して「どれか一つ」を表すユニオン型(`|`で結ばれた型)を作るマジックです。

// さっき作った型
type PenBoxType = {
red: string;
blue: string;
black: string;
};

// keyofをくっつけると……?
type PenKeys = keyof PenBoxType;

// 出来上がる型: “red” | “blue” | “black”

なんと、「”red”か”blue”か”black”のどれかの文字列ですよ!」という限定された型(ユニオン型)が一瞬で出来上がりました。

—

3. 合体! `keyof typeof` で実務の波を乗りこなそう

さて、ここまでくればもうお気づきですね。
この2つをドッキングさせたのが、実務で毎日と言っていいほど見かける `keyof typeof` です。

「JavaScriptのオブジェクト(実物)から型を推論して(`typeof`)、そのキーだけをユニオン型として抜き出す(`keyof`)」という一連の流れを、一撃でやってのけます。

実際のWeb制作やアプリケーション開発で、よくあるシチュエーションを見てみましょう。

💻 実用コード例:ユーザーの権限(ロール)管理

例えば、管理画面などで「管理者」「編集者」「一般ユーザー」を切り替えるセレクトボックスを作るとします。

// 1. まずは設定オブジェクトを普通に定義する
const USER_ROLES = {
ADMIN: “管理者”,
EDITOR: “編集者”,
MEMBER: “一般会員”,
} as const; // ※ここでの `as const` がプロの技!

// 2. 「keyof typeof」を使って、キーの型を自動生成する
// これで type Role = “ADMIN” | “EDITOR” | “MEMBER” になります!
type Role = keyof typeof USER_ROLES;

// — 使い方 —
// 関数には、勝手な文字列を渡させず、定義したキーだけを受け取るように強制できる
function printUserRole(role: Role) {
console.log(`現在の権限は ${USER_ROLES[role]} です。`);
}

// 使える例
printUserRole(“ADMIN”); // OK! “管理者” と出力されます

// やっちゃいけない例(TypeScriptが赤く波線を出して止めてくれます!)
// printUserRole(“SUPER_HACKER”);
// ❌ 引数の型に “SUPER_HACKER” なんて存在しないよ!と怒られます

ここで、ちょっとしたプロの裏技としてコードにこっそり仕込んだ `as const`(常数アサーション) についてもお話ししておきますね。

オブジェクトを定義するときに、末尾に `as const` をつけると、「このオブジェクトの中身は絶対に書き換えられないし、値もただの文字列じゃなくて『その文字そのもの(リテラル型)』として固定するよ!」とTypeScriptにお願いできます。
`keyof typeof` を使うときは、この `as const` とセットで覚えるのが現場の黄金ルールです。これがないと、型が広がりすぎてうまくいかないことがあるので、ぜひセットで呪文として唱えてくださいね。

—

4. まとめ:つまずいたときは、お道具箱を思い出して

いかがでしたでしょうか?
最初は見慣れない `keyof typeof` という並びも、分解して意味を知ってみれば、私たちのコーディングを強力に守ってくれる頼もしい相棒であることが分かっていただけたかと思います。

1. `typeof` で「実物」から設計図をパクり、
2. `keyof` でその設計図から「見出し(キー)」だけを抜き出す。

もし実務で「あれ、これどう書くんだっけ?」と手が止まったら、机の上のお道具箱を思い出してくださいね。
あなたが書くTypeScriptのコードが、もっともっと楽しく、安全で快適なものになりますように。

チーフアーキテクトの私でした!また次回の記事でお会いしましょう!

コメント

タイトルとURLをコピーしました