Generics(ジェネリクス)は、異なる型で動作しながら厳密な型の安全性を維持する汎用的なコードを書くことを可能にします。
使用法の構文:
function identity<T>(value: T): T { return value; } const x = identity<string>('test'); // T = string
使用される場所:
型制限のある例:
function getFirst<T extends { length: number }>(arr: T): T { return arr[0]; }
質問:ジェネリックパラメータを持つ関数を呼び出す際に具体的な型を指定する必要があるか?
回答:
必要ありません。TypeScriptは、可能な場合は渡された値に基づいて型を自動的に推論します。ただし、値から型が明確でない場合や複数の選択肢がある場合は、明示的に指定することが便利です。
function identity<T>(value: T): T { return value; } identity(5); // T = number(自動) identity<string>('s'); // T = string(明示的)
物語
eコマースプロジェクトで異なるエンティティのためのジェネリックリポジトリを作成しましたが、型制限を忘れてしまいました。その結果、ジェネリックには任意のオブジェクトが含まれ、互換性のないフィールドを持つエンティティが一度保存されました。型はエラーから保護されませんでした。
物語
テンプレート関数に配列を渡しましたが、要素の型を持つ配列を受け取ると期待していました。しかし、関数はany[]を返しました。なぜなら、ジェネリックが明示的に指定されておらず、TypeScriptが型を推論できなかったからです。エラーは本番環境でのみ気づかれました。
物語
初心者の開発者が型制限なしのジェネリッククラスを作成し、すべての型に存在しないフィールドを使用しました。コンパイラはエラーを出さなかったが、存在しないプロパティにアクセスした際に全機能が壊れてしまいました。