TypeScript のコードを読むとき、ジェネリクスが頻出すると「型が何を表しているのか分からない…」と戸惑うことはありませんか?
この記事では、プログラミング初心者でもすぐに実践できる、ジェネリクスを読み解くための 5 つのコツ を紹介します。実務でよく見かける Array<T> や Promise<T> だけでなく、独自実装の汎用関数でも活用できるので、ぜひ手元のエディタで試してみてください。
1. 型エイリアスで「意味」を付与する
ジェネリスは <T> のように抽象的です。
T が何を指すかを明示すると、コード全体の可読性が格段に上がります。
type User = { id: number; name: string };
type Result<T> = { ok: true; data: T } | { ok: false; error: string };
function fetchUser(): Promise<Result<User>> {
// 省略
}
Result<User> と見るだけで「ユーザー取得結果」だとすぐ分かります。
ポイント: 可能な限り具体的な型名をエイリアスに置き換える習慣をつけましょう。
2. デフォルト型で「省略可能」な部分を減らす
汎用関数にデフォルト型を設定すると、呼び出し側で型引数を書かなくても意味が通ります。
function mapArray<T, U = T>(arr: T[], fn: (item: T) => U): U[] {
return arr.map(fn);
}
mapArray([1, 2, 3], x => x * 2) のように書くだけで U が自動的に number と推論され、コードがシンプルに。
3. インターフェースで「契約」を可視化
ジェネリクスを使うときは、どのプロパティが必須か をインターフェースで表すと把握しやすくなります。
interface Paginated<T> {
items: T[];
total: number;
page: number;
perPage: number;
}
Paginated<Post> と見るだけで「ページングされた記事リスト」だと直感的に分かります。
4. IDE の「ホバー」や「型情報」機能を活用
VSCode などのエディタは、マウスオーバーで型情報を表示します。
<T> が何を指すか不明なときは Ctrl+クリック で定義へジャンプし、型エイリアスやインターフェースを確認しましょう。
これだけで「ブラックボックス」感が激減します。
5. 小さなサンプルで「実際に動かす」
抽象的な型は実際に実行してみるとイメージが固まります。
以下は、ジェネリック関数 filterByKey の最小サンプルです。コンソールに結果を出すだけで、型がどのように伝搬するかが分かります。
function filterByKey<T, K extends keyof T>(arr: T[], key: K, value: T[K]): T[] {
return arr.filter(item => item[key] === value);
}
// 使用例
type Product = { id: number; name: string; price: number };
const products: Product[] = [
{ id: 1, name: "Pen", price: 100 },
{ id: 2, name: "Notebook", price: 300 },
];
const cheap = filterByKey(products, "price", 100);
console.log(cheap); // [{ id: 1, name: "Pen", price: 100 }]
K extends keyof T が「key は T のプロパティ名だけに限定」されていることがポイントです。実際に走らせてみると、型エラーが出ないことが確認できます。
まとめ
- 型エイリアスで意味付け
- デフォルト型で省略を減らす
- インターフェースで契約を明示
- IDE の型情報をフル活用
- 小さなサンプルで手を動かす
これらのコツを意識すれば、ジェネリクスが多用されたコードでも「何が起きているか」をすぐに把握できるようになります。まずは身近なユーティリティ関数から試してみてください。