TypeScriptの「Record型」を使いこなせ:型安全なデータ構造の真髄
やあ。現場でコードを書いていて、こんな場面に出くわしたことはないか?
「APIから返ってきた謎の辞書型オブジェクトをどう型付けするか」
「特定のキーセットを強制したい設定オブジェクトをどう定義するか」
そんな時、反射的に `{[key: string]: any}` と書いてしまうのは、もう卒業しよう。フロントエンドのコードベースを堅牢に保つための、`Record
Record型とは何か、なぜ使うのか
TypeScriptにおいて、`Record
JavaScriptのエンジンレベルで見れば、結局はただのプレーンなオブジェクト(`{}`)に過ぎない。しかし、TypeScriptの型システムという「守護神」を通すことで、「存在しないキーへのアクセス」や「型不一致な値の代入」を、コンパイル時に、つまりコードを実行する前に叩き潰せるようになる。
これが、我々フロントエンドエンジニアがランタイムエラーから解放されるための第一歩だ。
実務で輝く「Record型」の活用パターン
まずは、現場でよく使う「辞書」としての基本的な使い方を見ていこう。
/
- ユーザーのロールごとに権限レベルを管理する辞書
/
type Role = ‘admin’ | ‘user’ | ‘guest’;
// Recordを使えば、Roleに定義されたキーが全て存在することを型レベルで保証できる
const rolePermissions: Record
admin: 100,
user: 50,
guest: 0,
};
// もしここに足りないキーがあれば、TypeScriptが即座にエラーを吐いてくれる
// これがインターフェースを直接書くよりも圧倒的に保守性が高い理由だ
1. キーの動的な縛り
`keyof` と組み合わせることで、既存の型から安全にキーを抽出できる。これがRecord型の真骨頂だ。
interface PageMeta {
title: string;
path: string;
}
// 他の型定義から特定のキーだけを抽出してRecordを作る(非常に強力)
type PageRegistry = Record<'home' | 'about', PageMeta>;
const pages: PageRegistry = {
home: { title: ‘ホーム’, path: ‘/’ },
about: { title: ‘概要’, path: ‘/about’ },
};
なぜ `any` や `unknown` を避けるべきなのか
初心者がよくやる `Record
ブラウザのJavaScriptエンジンは、あなたが渡したオブジェクトがどんな形であれ動かそうとする。だが、その中身が何であるかという「規約」を失った瞬間、開発チームは崩壊する。`Record
注意点:Record型が万能ではないケース
一つ、経験から伝えておきたい。「キーが不確定な場合」には無理にRecordを使わず、`Partial
APIから返ってくるデータが必ずしも全てのキーを持っているとは限らないだろう?そんな時にRecordを使うと、全てのキーが必須だとコンパイラに誤認され、`undefined` の海で溺れることになる。
// キーが揃っているか分からないAPIレスポンスの処理
type UserStats = Record
// プロパティが欠けている可能性があるなら、Partialで包むのが現場の流儀だ
const stats: Partial
loginCount: 10,
// 実際には存在しないキーがあっても、Partialならエラーにならない
};
まとめ:次にコードを書くときへのアドバイス
1. 「辞書型」を作るときは、まず `Record` を検討せよ。
2. キーをハードコーディングせず、Union型(`’a’ | ‘b’`)を定義して使え。
3. APIレスポンスのように不完全なデータが来る場合は、`Partial
TypeScriptの型定義は、単なる制約じゃない。それは、未来の自分やチームメイトに対する「ドキュメント」であり、コードの品質を保証する「防波堤」だ。
今日から `any` を捨てて、適切な `Record` を定義してみよう。たったそれだけで、君の書くコードの「格」が一段上がるはずだ。何か詰まったら、いつでも聞いてくれ。現場からは以上だ。

コメント