TypeScriptジェネリクスをサクッと理解【その1 型定義に対して使うジェネリクス】
TypeScriptのジェネリクスはむずかしい?
下記のような「T」や「K」の入ったTypeScriptのコードを「ジェネリクス」といいます。
function example<T, K>(a: T, b: K): [T, K]{
return [a, b]
}
「T」や「K」が入っていて、見た目だけですでに難しく感じます。
実際、ジェネリクスに苦手意識を感じている人は世界中にたくさんいます。
しかし、ひとつひとつ理解をしていけば実はシンプルなのがジェネリクスです。
4回に分けて紹介します。
この記事は全4回の1つ目です
ジェネリクスは何に使う?
ジェネリクスとは、「とりあえずの仮置きとして置かれた、実質的な中身のない型情報」のことです。
「型はあとで決める」という柔軟さと、複数のオブジェクトやfunctionに対して使い回すことのできる汎用性がジェネリクスのメリットになります。
とはいえ、このような言葉の説明ではわかりづらいのでコードで確認しましょう。
ジェネリクスを「型定義に対して使うもの(1回目/本記事)」と「functionに対して使うもの(2回目)」に分け、最後に「両方を合わせたケース(3回目)」と、「複数のジェネリクスの使い方(4回目)」を紹介します。
本記事で触れるのは1つ目の「型定義に対して使うもの」です。
ジェネリクスを型定義に対して使う
次のコードがあったとします
// main.ts
const userOne: any = {
data: "太郎",
color: "赤"
}
anyの代わりに、しっかりした型定義を用意しましょう。
// main.ts
// 👇追加
type User = {
data: string;
color: string;
}
// 👆追加
const userOne: User = { // 修正
data: "太郎",
color: "赤"
}
しかしもしここで、次のような2つ目のデータがあると、この型定義ではエラーが出ます。userTwoのdataの型がnumberだからです。
// main.ts
type User = {
data: string;
color: string;
}
const userOne: User = {
data: "太郎",
color: "赤"
}
// 👇追加
const userTwo: User = {
data: 2002,
color: "緑"
}
// 👆追加
なので型定義Userをもっと抽象化して、より広く使えるようにしましょう。
次の変更を加えてください。
// main.ts
type User<T> = { // 変更
data: T; // 変更
color: string;
}
const userOne: User = {
...
<T>は仮置きの型、実質的な中身のない型に過ぎません。
これを意味あるものにするには、実際の型を注入する必要があります。次のコードを追加しましょう。
// main.ts
type User<T> = {
data: T;
color: string;
}
const userOne: User<string> = { // 追加
data: "太郎",
color: "赤"
}
const userTwo: User<number> = { // 追加
data: 2002,
color: "赤"
}
これが型定義対して使うジェネリクスです(型引数/Type parametersとも呼ばれます)。
一般的には<T>や<K>、<U>などが使われますが、<ArgType>や<Name>など任意の文字でも大丈夫です。
本連載2回目の次の記事では、「functionに対するジェネリクス」を解説します。
2024年3月にReact + TypeScriptの新刊書をリリースしました。
ジェネリクスを含む、基礎から応用までの幅広い範囲をカバーしており、TypeScript + React入門者から、中級者の人にもっとも学びがある内容になっています。
この記事が気に入ったらサポートをしてみませんか?