こんにちは!TypeScriptの型定義の世界へようこそ、チーフアーキテクトの私です。
TypeScriptを書き始めの頃って、「string」とか「number」みたいな基本の型を一通り覚えて、「よし、いけるぞ!」と思った矢先に、なんだか見慣れない記号や複雑な型定義にぶつかって、「うっ…」と手が止まっちゃうこと、ありませんか?
大丈夫ですよ、その「うっ…」となる感覚、誰もが通る道です。今日一緒に紐解いていく「Indexed Access Types(インデックス型アクセス)」も、最初は名前からして難しそうに見えますよね。
でも、安心してください。実はこれ、私たちの普段の生活にある「ある便利な仕組み」と全く同じなんです。肩の力を抜いて、一緒に見ていきましょう!
—
そもそも「Indexed Access Types」ってなに?
いきなり難しい英語が出てきましたが、日本語で言うと「オブジェクトの中から、特定のプロパティの型だけをピンポイントで抜き出す技」です。
身近な例えでお話ししますね。
あなたの手元に、お気に入りの洋服がぎっしり詰まった「クローゼット(オブジェクト)」があるとします。
そのクローゼットには、こんなルールで服がしまわれています。
const myCloset = {
top: “お気に入りのパーカー”,
bottom: “動きやすいデニム”,
shoes: “真っ白なスニーカー”
};
普段、私たちは「ボトムスのエリアにあるものを取り出したいな」と思ったら、`myCloset.bottom` あるいは `myCloset[‘bottom’]` のようにして、中のものを取り出しますよね。JavaScriptの基本です。
TypeScriptの「Indexed Access Types」は、これの【型バージョン】なんです。
実物の洋服を取り出す代わりに、「ボトムスのエリアに入っている『服のサイズ(型)』だけを教えて!」と型システムにお願いする仕組みなんですよ。
—
基本の書き方をみてみよう
百聞は一見にしかず。実際のコードを見てみましょう。
まずは、お買い物のユーザー情報を表す型を定義してみます。
// ユーザーの情報をまとめた型
type User = {
id: number;
name: string;
email: string;
isPremium: boolean;
};
ここで、「あ、そういえば別の場所で、このUser型の `name` プロパティの型だけを使い回したいな」と思ったとします。もちろん `string` と直接書いてもいいのですが、もし将来、設計が変わって `name` がオブジェクトになったりしたら、あちこちのコードを直さないといけなくなって面倒ですよね。
そこで登場するのが、インデックス型アクセス(`Type[‘key’]`)です!
// User型の中にある ‘name’ プロパティの型(string)を取り出す
type UserNameType = User[‘name’]; // 中身は string になります!
// こうやって使うこともできます
const myName: UserNameType = “山田太郎”;
どうですか? `User[‘name’]` と書くだけで、`User` という大きな設計図から、`name` の部分だけをきれいに切り出すことができました。
まるで、ハサミでチョキっと切り抜くみたいで、なんだかワクワクしませんか?
—
なぜこの機能が実務ですごく重宝されるの?
「へえ、ピンポイントで型を取り出せるんだね。でも、わざわざそんなことしなくても、普通に `string` って書けばよくない?」
そう思ったそこのあなた、鋭いですね!
実はこのインデックス型アクセスが真価を発揮するのは、「APIのデータ構造」や「大きな設定ファイル」を扱う現場です。
例えば、バックエンドのエンジニアから「こういう形式のデータ(型)を送るね」と、次のような巨大な型をもらったとします。
type ApiResponse = {
status: number;
message: string;
data: {
userId: string;
profile: {
firstName: string;
lastName: string;
age: number;
};
};
};
この中の `age`(年齢)の型だけを別のコンポーネントで使いたいとき、わざわざ奥深くを辿って型を書き直すのは大変です。でも、インデックス型アクセスを使えば、こう書けちゃいます。
// 連なるカギ括弧(ブラケット)で、奥深くの型も一発で取れる!
type UserAge = ApiResponse[‘data’][‘profile’][‘age’];
// 結果として number 型が取得できます
すごいですよね!大元の `ApiResponse` の構造がもし変わったとしても、この `UserAge` 型は自動的に追従してくれます。保守性がグッと上がるので、チーム開発では本当に重宝するテクニックなんです。
—
つまずきやすいポイントと「お薬」
ここで、初心者の人がよくやってしまう「うっかりミス」をひとつご紹介しておきますね。
よくあるのが、「値(変数)」に対してこの書き方をしてしまうケースです。
const userObject = {
name: “佐藤”,
age: 28
};
// ❌ エラーになっちゃう例!
// type NameType = userObject[‘name’];
「あれ?エラーが出たぞ……」と焦るかもしれませんが、大丈夫です。
インデックス型アクセスは、あくまで「型(`type` や `interface` で定義したもの)」に対して使うものなんです。
もし、すでにある「変数(値)」から型を取り出したい場合は、TypeScriptの魔法の言葉 `typeof` を一緒に組み合わせてあげます。
const userObject = {
name: “佐藤”,
age: 28
};
// ⭕️ typeof で一度「型」に変換してからならOK!
type NameType = (typeof userObject)[‘name’]; // string 型が取れます
実務の現場では、APIから返ってきたレスポンスのモックデータなどに対して、この `(typeof 〇〇)[‘key’]` を使うテクニックが本当によく登場します。もしエラーが出たら、「あ、値から直接取ろうとしちゃったかな?」と思い出して、`typeof` をそっと添えてあげてくださいね。
—
まとめ
いかがでしたでしょうか?
Indexed Access Types(インデックス型アクセス)は、難しそうな名前をしていますが、要するに「大きな型から、必要な部分だけをスマートに借りてくるための便利な道具」です。
1. `Type[‘property’]` の形で特定のプロパティの型を抽出できる
2. 深い階層のプロパティも `[‘a’][‘b’][‘c’]` のように繋げて取得できる
3. すでに存在する変数から型を取りたいときは `typeof` を組み合わせる
最初は覚えることが多くて大変に感じるかもしれませんが、日々のコーディングの中で「あ、ここであの切り出しの技が使えるかも!」と気づけるようになると、TypeScriptを書くのが何倍も楽しく、そしてコードがぐっと洗練されていきますよ。
あなたのTypeScriptライフが、少しでも快適で楽しいものになりますように。
それでは、また次の現場でお会いしましょう!チーフアーキテクトでした。

コメント