
TypeScriptのジェネリクスをマスターして、どんな型にも対応できる最強のコードを書こう!🚀
TypeScriptのジェネリクスとは?
TypeScriptのジェネリクスは、関数、インターフェース、クラスを定義する際に、型をパラメータ化する機能です。これにより、様々な型に対して同じロジックを適用できる、再利用性の高いコードを書くことができます。
ジェネリクスを使用すると、型安全性を保ちながら、柔軟なコードを作成できます。コンパイル時に型チェックが行われるため、実行時のエラーを減らすことができます。
例えば、配列の要素を操作する関数を考えます。ジェネリクスを使わない場合、特定の型(例えばstring
型)の配列に対してのみ動作する関数を書くことになります。しかし、ジェネリクスを使えば、number
型やboolean
型など、様々な型の配列に対して動作する汎用的な関数を作成できます。
ジェネリクスの基本的な使い方
ジェネリクスは、山括弧 <>
を使用して型パラメータを定義します。一般的に、T
、U
、V
などの大文字のアルファベットが型パラメータとして使用されます。
以下は、ジェネリクスを使用した関数の例です。
function identity<T>(arg: T): T {
return arg;
}
let myString: string = identity<string>("hello"); // myStringは"hello"というstring型
let myNumber: number = identity<number>(123); // myNumberは123というnumber型
let myBoolean: boolean = identity<boolean>(true); // myBooleanはtrueというboolean型
この例では、identity
関数は型T
の引数を受け取り、同じ型の値を返します。identity<string>("hello")
のように、関数を呼び出す際に型パラメータを明示的に指定することもできますが、TypeScriptは型推論により自動的に型を決定することもできます。
let myString = identity("hello"); // TypeScriptは自動的にstring型を推論
let myNumber = identity(123); // TypeScriptは自動的にnumber型を推論
let myBoolean = identity(true); // TypeScriptは自動的にboolean型を推論
ジェネリクスを使ったインターフェースとクラス
ジェネリクスは、インターフェースやクラスでも使用できます。これにより、インターフェースやクラスのメンバ変数の型をパラメータ化できます。
以下は、ジェネリクスを使用したインターフェースの例です。
interface GenericInterface<T> {
value: T;
getValue(): T;
}
class MyClass<T> implements GenericInterface<T> {
value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
let stringClass = new MyClass<string>("hello");
let numberClass = new MyClass<number>(123);
この例では、GenericInterface
インターフェースは型T
のvalue
プロパティとgetValue
メソッドを持ちます。MyClass
クラスは、このインターフェースを実装しており、コンストラクタでvalue
プロパティを初期化し、getValue
メソッドでその値を返します。
ジェネリクスの制約
ジェネリクスを使用する際に、型パラメータに制約を設けることができます。これにより、特定の型のみを受け入れるように制限できます。制約は、extends
キーワードを使用して定義します。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Lengthwiseインターフェースのlengthプロパティにアクセスできる
return arg;
}
loggingIdentity({value: "test", length: 10}); // OK
// loggingIdentity(123); // エラー: number型にはlengthプロパティが存在しない
この例では、loggingIdentity
関数は、Lengthwise
インターフェースを実装する型T
のみを受け入れます。Lengthwise
インターフェースは、length
プロパティを持つオブジェクトを定義しています。したがって、この関数に渡される引数は、必ずlength
プロパティを持つ必要があります。
参考リンク
まとめ
TypeScriptのジェネリクスは、型安全性を保ちながら、再利用性の高いコードを書くための強力なツールです。関数、インターフェース、クラスでジェネリクスを使用することで、様々な型に対応できる汎用的なコードを作成できます。ジェネリクスの制約を使用することで、型パラメータに特定の要件を課すこともできます。ジェネリクスを効果的に活用して、より堅牢で保守性の高いTypeScriptコードを書きましょう。