はじめに
こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
TypeScript を使った React 開発で、ジェネリクス(Generics) という言葉を初めて聞き、それについて少し調べてみました。
本記事では、ジェネリクスの基本から、React における具体的な活用例までを解説します。
ジェネリクスの基本
ジェネリクスとは「型を引数として渡す仕組み」です。
TypeScript の関数を例にすると次のようになります。
const identity = <T>(value: T): T => {
return value;
};
const num = identity<number>(42); // number
const str = identity<string>('Hi'); // string
<T>
の部分が型パラメータです。呼び出し時に具体的な型が決まります。
これを React でも活用できます。
React でのジェネリクスの使いどころ
1. ジェネリックなフック
API リクエストの結果など、型が変わる可能性のあるデータを扱うフックにジェネリクスは便利です。
import { useState } from 'react';
const useFetch = <T>(url: string) => {
const [data, setData] = useState<T | null>(null);
const fetchData = async () => {
const res = await fetch(url);
const json = (await res.json()) as T;
setData(json);
};
return { data, fetchData };
};
// 利用例
type User = { id: number; name: string };
const { data, fetchData } = useFetch<User>('/api/users');
呼び出し側で <User>
と型を渡すことで、戻り値 data
が User | null
だと推論されます。
2. ジェネリックなコンポーネント
フォーム入力やリスト表示など、どんなデータ型でも共通化したい UI にジェネリクスを使えます。
type SelectProps<T> = {
options: T[];
getLabel: (item: T) => string;
onSelect: (item: T) => void;
};
const Select = <T,>({ options, getLabel, onSelect }: SelectProps<T>) => {
return (
<select onChange={(e) => onSelect(options[e.target.selectedIndex])}>
{options.map((option, idx) => (
<option key={idx}>{getLabel(option)}</option>
))}
</select>
);
};
// 利用例
type Subject = { id: number; name: string };
<Select<Subject>
options={[
{ id: 1, name: '数学' },
{ id: 2, name: '英語' },
]}
getLabel={(s) => s.name}
onSelect={(s) => console.log(s.id)}
/>;
Select<Subject>
とすることで、options
の型が Subject[]
だと保証されます。
まとめ
-
ジェネリクスは「型をパラメータとして渡せる仕組み」
-
React では以下の場面で特に有効
- 型の異なるデータを扱うカスタムフック
- 型に依存しない再利用性の高い UI コンポーネント