TypeScript ジェネリッククラス オブジェクト作成
TypeScriptでジェネリッククラスから型パラメータで新しいオブジェクトを作成する
TypeScriptでは、ジェネリッククラスを使用することで、型をパラメータとして受け取り、その型に基づいて動作する柔軟なクラスを作成できます。この機能を活用して、型パラメータで指定された型の新しいオブジェクトを作成することも可能です。
基本的な例
class MyClass<T> {
private data: T;
constructor(data: T) {
this.data = data;
}
createInstance(): T {
return new T(); // 型パラメータTに基づいて新しいオブジェクトを作成
}
}
const myNumberClass = new MyClass<number>(10);
const numberInstance = myNumberClass.createInstance(); // number型の新しいオブジェクトを作成
解説
-
ジェネリッククラスの定義
class MyClass<T>
:T
を型パラメータとして受け取るジェネリッククラスを定義します。private data: T;
:T
型のデータを保持するプロパティを定義します。
-
コンストラクタ
-
createInstance()メソッド
return new T();
:T
型の新しいオブジェクトを作成し、返します。
ポイント
- 型パラメータは、複数の型を扱う必要がある場合や、コードの汎用性を高めるために使用されます。
T
は、ジェネリッククラスを使用する際に具体的な型に置き換えられます。new T()
の構文は、型パラメータT
に基づいて新しいオブジェクトをインスタンス化します。
応用例
- データ構造
ジェネリッククラスを使って、任意の型のデータを格納するデータ構造(例えば、リスト、マップ)を作成できます。 - ファクトリーパターン
ジェネリッククラスを使用して、さまざまな型のオブジェクトを生成するファクトリーメソッドを実装できます。
注意
- 型パラメータには、制約(constraints)を設けることもできます。
- 型パラメータは、クラス内の他のメンバー(プロパティ、メソッド)でも使用できます。
- 型パラメータは、必ずコンストラクタまたはメソッドの引数として渡す必要があります。
コードの解説
class MyClass<T> {
private data: T;
constructor(data: T) {
this.data = data;
}
createInstance(): T {
return new T(); // 型パラメータTに基づいて新しいオブジェクトを作成
}
}
const myNumberClass = new MyClass<number>(10);
const numberInstance = myNumberClass.createInstance(); // number型の新しいオブジェクトを作成
コードの行ごとの解説
-
class MyClass<T>
MyClass
という名前のジェネリッククラスを定義します。<T>
の部分が重要で、このT
が型パラメータを表します。つまり、このクラスは、どんな型のデータでも扱うことができるように、型を汎化しているのです。
-
private data: T;
data
という名前のプライベートなプロパティを定義します。- このプロパティの型は、型パラメータ
T
で指定された型になります。
-
constructor(data: T)
- クラスのインスタンスを作成する際に、
data
という引数を受け取ります。
- クラスのインスタンスを作成する際に、
-
createInstance(): T { ... }
createInstance
という名前のメソッドを定義します。- このメソッドは、
T
型の新しいオブジェクトを作成して返します。 new T()
の部分が特に重要で、ここで型パラメータT
を使って、新しいオブジェクトを生成しています。
-
const myNumberClass = new MyClass<number>(10);
MyClass
クラスのインスタンスを生成します。- 型パラメータ
T
の部分にnumber
を指定しているので、このインスタンスはnumber
型のデータを扱うことになります。 - コンストラクタに
10
という数値を渡しているので、data
プロパティには10
が格納されます。
-
const numberInstance = myNumberClass.createInstance();
myNumberClass
のcreateInstance
メソッドを呼び出して、新しいnumber
型のオブジェクトを作成します。- この新しいオブジェクトは、
numberInstance
変数に代入されます。
動作の仕組み
- このように、ジェネリッククラスを使うことで、同じコードを様々な型に対して再利用することができます。
- 生成されたオブジェクトは、
createInstance
メソッドの戻り値として返されます。 createInstance
メソッドが呼ばれると、new T()
の部分で、T
に指定された型(この場合はnumber
)の新しいオブジェクトが生成されます。
このコードは、TypeScriptのジェネリッククラスの基本的な使い方を示しています。型パラメータを使うことで、コードの柔軟性と再利用性を高めることができます。
さらに詳しく知りたい方へ
- ジェネリック関数
関数もジェネリックにできます。 - ジェネリックインターフェース
インターフェースもジェネリックにできます。 - ジェネリック型制約
型パラメータに制約を与えることで、より安全なコードを書くことができます。
これらの概念を組み合わせることで、より複雑なジェネリックプログラミングを行うことができます。
- 「ジェネリック型制約に
extends
キーワードを使う場面はどのような時ですか?」 - 「ジェネリッククラスで配列を扱うにはどうすればよいですか?」
TypeScriptのジェネリッククラスで新しいオブジェクトを作成する:代替方法と詳細
ジェネリッククラスを用いたオブジェクト作成の代替方法
TypeScriptで、ジェネリッククラスを用いて型パラメータから新しいオブジェクトを作成する方法は、非常に強力かつ柔軟なアプローチです。しかし、状況によっては、他の方法も検討する価値があります。
インターフェースとファクトリー関数
- 例
- デメリット
- メリット
- クラスのオーバーヘッドを避けることができる。
- 異なる実装を持つ複数のファクトリー関数を用意できる。
interface IFactory<T> {
create(): T;
}
const numberFactory: IFactory<number> = {
create() {
return Math.random();
}
};
const numberInstance = numberFactory.create();
ジェネリック型とnew演算子
- メリット
- シンプルで直感的。
function createInstance<T extends { new(): T }>() {
return new T();
}
const numberInstance = createInstance<number>();
ジェネリックユーティリティ型
- デメリット
- 少し複雑になる可能性がある。
- メリット
- 型レベルでの操作が可能。
- 高度な型操作に利用できる。
type Constructor<T> = new (...args: any[]) => T;
function createInstance<T>(ctor: Constructor<T>): T {
return new ctor();
}
それぞれの方法の比較と選択
typescript generics