TypeScriptジェネリクスをサクッと理解【その4 複数のジェネリクスをつかう】
TypeScriptのジェネリクスはむずかしい?
この記事はジェネリクスをサクッと解説する全4回の記事の4つ目です。
ジェネリクスを複数使う
次のコードがあったとします。
// main.ts
function example(a: string, b: string){
return [a, b]
}
console.log(
example("三島", "由紀夫")
)
aとbの2つのデータをexampleに渡して実行後すると、aとbは「[a, b]」という配列になってreturnされます。
上の例では「[三島, 由紀夫]」とブラウザのコンソールに表示されます。
TypeScriptが推測してくれているので不要ですが、returnするデータの型を書いてみましょう。
配列のデータがreturnされるので、次のように書きます。
// main.ts
👇追加
function example(a: string, b: string): [string, string]{
return [a, b]
}
...
さて、ここで次のようなデータを入れようとするとエラーが出ます。「2005」がnumber型だからです。
// main.ts
function example(a: string, b: string): [string, string]{
return [a, b]
}
console.log(
example("三島", "由紀夫")
)
// 👇追加
console.log(
example(2005, "谷崎")
)
// 👆追加
どのような型のデータにもexampleのfunctionが対応できるようにするために、ジェネリクスを使いましょう。
まず渡すデータを仮置きのTとKに変えます。
本連載1回目の「型定義に対して使うジェネリクス」でも書きましたが、ここで使う文字は「<ArgType>」や「<Name>」など任意の文字も可です。
// main.ts
👇追加
function example(a: T, b: K): [string, string]{
return [a, b]
}
...
渡すデータの型が仮のものになったので、returnするデータの型も仮のものに変える必要があります。
// main.ts
👇追加
function example(a: T, b: K): [T, K]{
return [a, b]
}
...
最後に、このfunctionではジェネリクスを使っていると明示するコードを追加します。
// main.ts
👇追加
function example<T, K>(a: T, b: K): [T, K]{
return [a, b]
}
...
今回も型の推測によってこの時点でエラーは消えますが、次のように実際の型情報を注入する必要があるケースも存在します。
// main.ts
function example<T, K>(a: T, b: K): [T, K]{
return [a, b]
}
console.log(
example<string, string>("三島", "由紀夫") // 追加
)
console.log(
example<number, string>(2005, "谷崎") // 追加
)
React + TypeScript開発においては、型定義に対するジェネリクスとfunctionに対するジェネリクスが同時に使われ、さらにジェネリクスの数も<T>のように1つだけでなく、<T, K, U>などと複数使われることがあります。
ジェネリクスはいつ使う? そして注意点は?
ジェネリクスが欠かせないのは、npmパッケージやライブラリの開発時です。
これらは多くの人が使うものであり、汎用的であることがマストなので、柔軟性を付与できるジェネリクスが活躍するのです。
しかし、ごく限られた人だけ、あるいは自分だけしか使わないファイルやReactコンポーネントにジェネリクスを過度に使うことは、むしろいたずらに抽象度を高め、時間が経って見返すと何をしているのか自分でもわからなくなってしまう可能性を高めます。
ジェネリクスを使うときはこの点に注意しましょう。
2024年3月にReact + TypeScriptの新刊書をリリースしました。
ジェネリクスを含む、基礎から応用までの幅広い範囲をカバーしており、TypeScript + React入門者から、中級者の人にもっとも学びがある内容になっています。
https://monotein.base.shop/p/00002
この記事が気に入ったらサポートをしてみませんか?