TypeScriptの世界へようこそ。型システムを単なる「エラーを防ぐための道具」だと思っていませんか?実は、TypeScriptの型システムは、それ自体が「コンパイル時に実行される関数型プログラミング言語」なのです。
今回は、現場で誰もが一度は頭を抱える「APIの命名規則変換」を題材に、`Mapped Types`(マップ型)という強力な武器を使って、オブジェクトのキーを自在に操る極意を伝授します。
—
1. なぜ「型による変換」が必要なのか?
フロントエンドでAPIを叩くとき、バックエンドから返ってくるJSONがスネークケース(例: `user_id`)であることは珍しくありません。しかし、JavaScript/TypeScriptの世界ではキャメルケース(例: `userId`)で扱うのが一般的ですよね。
これを手動で変換するのではなく、「型定義さえ書けば、あとはコンパイラが自動でキーを変換してくれる」という仕組みを作れたら、コードはどれほど堅牢になるでしょうか。
2. マップ型(Mapped Types)という魔法
マップ型とは、既存の型から新しい型を生成する「型のためのループ処理」です。まずは基本形を見てみましょう。
type Original = {
user_id: number;
user_name: string;
};
// Mapped Types: Originalの全キーを走査して、型をstringに変更する例
type Stringify
[K in keyof T]: string;
};
type Result = Stringify
// 評価結果: { user_id: string; user_name: string; }
ここで重要なのは `[K in keyof T]` という記法です。
- `keyof T`: オブジェクトのキーをすべて取り出す(Union型になります)
- `K in …`: そのキーを一つずつ順番に取り出して処理する(for文のようなもの)
3. 実践:スネークからキャメルへの型変換
では、本題のキー変換を実装します。ここでは、TypeScriptのテンプレートリテラル型という高度な機能を使います。
// 1. スネークケースをキャメルケースに変換するユーティリティ型
type SnakeToCamel = S extends `${infer Head}_${infer Tail}`
? `${Head}${Capitalize
: S;
// 2. マップ型を使って、オブジェクトの全キーを変換する
type CamelizeObject
[K in keyof T as K extends string ? SnakeToCamel
};
// — 使用例 —
type ApiResponse = {
user_id: number;
first_name: string;
created_at: string;
};
type User = CamelizeObject
/
評価結果:
type User = {
userId: number;
firstName: string;
createdAt: string;
}
/
コードの解説
- `infer`: 「推論」のキーワードです。`_` の前と後ろを切り出して変数のように扱っています。
- `as K extends string ? …`: マップ型の「キー再マッピング」機能です。単に値の型を変えるだけでなく、`K` というキーそのものの名称を変換して出力しています。
4. 初学者が陥りやすい「文法エラー」の罠
この領域を学ぶとき、多くの人が以下のエラーに直面します。
「型引数に制約がない」エラー
`type Camelize
解決策: `T extends object` と制約をつけましょう。
「再帰の深さ制限」エラー
複雑な型変換を繰り返すと、TypeScriptのコンパイラが「これ以上計算できません(Recursion depth limit)」と音を上げることがあります。これはTypeScriptがコンパイルパフォーマンスのために再帰回数に制限を設けているからです。実務ではあまりに深いネストは避け、適度なインターフェース分割を心がけてください。
5. 最後に:型を「書く」のではなく「組む」感覚を
TypeScriptを使いこなすということは、「データがどのように変形されるか」というアルゴリズムを型の中で再現するということです。
今回学んだ `Mapped Types` と `Key Remapping` は、大規模なアプリケーションになればなるほど、手書きの型定義ミスを減らす強力な盾になります。最初は難しく感じるかもしれませんが、一度この「型を組む」感覚を掴めば、TypeScriptは単なるチェックツールから、あなたの最強の設計パートナーへと進化します。
ここをクリアしたあなたは、もうTypeScriptの初学者ではありません。ぜひ、自分のプロジェクトでも「自動化できる型定義はないか?」と探す視点を持ってみてください。
それでは、また次の深淵でお会いしましょう!