こんにちは!TypeScriptの型定義の世界へようこそ。チーフアーキテクトの私です。
日々のフロントエンド開発、本当にお疲れ様です。型定義の勉強をしていると、「あれもこれも覚えなきゃいけなくて頭がパンクしそう……」なんて感じる瞬間、ありませんか?大丈夫です、そのモヤモヤはみんなが通る道ですし、あなたがしっかり向き合っている証拠です。
今回は、TypeScriptの数ある「ユーティリティ型」の中でも、ちょっとカッコよくて実務でめちゃくちゃ頼りになる`InstanceType
難しそうな名前をしていますが、恐れる必要はゼロです。身近な例えを交えながら、一緒に解きほぐしていきましょう!
—
1. クラスとインスタンスって、何だっけ?
`InstanceType`の本質に入る前に、まずは「クラス」と「インスタンス」の関係を整理しておきましょう。
TypeScriptにおけるクラス(Class)は、いわば「設計図」です。例えば、世の中にある「自動販売機」の設計図だと想像してください。
そして、その設計図をもとに実際に組み立てられて、街角にポツンと置かれた実物の自販機、あれが「インスタンス(実体)」です。
- クラス(Class) = 自販機の設計図(これ自体はお金も入れられないし、ジュースも出てこない)
- インスタンス(Instance) = 設計図から生まれた実物の自販機(実際にボタンを押して飲み物を買える)
プログラムを書いていると、「この設計図(クラス)から作られる実物(インスタンス)の型情報が欲しいな〜」という場面に出くわします。そんなとき、TypeScriptに「この設計図から生まれる実物の型を教えて!」と尋ねるための魔法の杖が、今回主役の `InstanceType
—
2. なぜ `InstanceType` が必要なの?
「わざわざそんなことしなくても、クラス名をそのまま型として使えばいいんじゃないの?」
鋭いですね!その通り、普段はクラスの名前をそのまま型として使えます。例えばこんな感じですね。
// カフェの注文を管理するクラス(設計図)
class CoffeeOrder {
drinkName: string = “カフェラテ”;
}
// クラス名をそのまま型として使えます
const myOrder: CoffeeOrder = new CoffeeOrder();
これでもう十分動くのですが、実務の現場では、「コンストラクタ関数(クラスそのもの)を他の関数に引数として渡す」ような高度なテクニックを使うことがあります。
例えば、「渡された設計図をもとに、自動でインスタンスを生成して初期化する工場(ファクトリー関数)を作りたい!」というときです。このとき、関数側で「どんなインスタンスが返ってくるのか」を正確に型推論させたいのに、クラスそのものの型(コンストラクタ型)を渡されているせいで、実物の型が分からなくなってしまう……というジレンマが起きるのです。
そんな「設計図から、生まれてくる実物の型を引っぺがしたい!」という場面で、`InstanceType
—
3. 実コードで見てみよう! `InstanceType` の使い方
百聞は一見にしかず。実際のコードを見てみましょう。
お手元のエディタにそのまま貼り付けて、挙動を確認してみてくださいね。
// 1. お買い物の「レシート」を表すクラス(設計図)を作成します
class Receipt {
shopName: string = “TypeScriptカフェ”;
totalAmount: number = 1200;
print(): void {
console.log(`${this.shopName}での お会計は ${this.totalAmount}円です。`);
}
}
// 2. 「Receiptという設計図そのもの」の型を、typeof で取得します
// ※ここがポイント!実物ではなく「クラスそのもの(コンストラクタ)」の型です
type ReceiptConstructor = typeof Receipt;
// 3. InstanceType を使って、「設計図」から「実物(インスタンス)の型」を抽出します!
type ReceiptInstance = InstanceType
// 4. 無事に実物の型になっているか確認してみましょう
// 下の定数は、ReceiptInstance 型を持つことになります
const todaysReceipt: ReceiptInstance = new Receipt();
todaysReceipt.print(); // 「TypeScriptカフェでの お会計は 1200円です。」と出力されます
ここで注目してほしいのは、`InstanceType
「`Receipt` という設計図の型」を放り込むと、TypeScriptが「あ、そこから生まれるのは `Receipt` クラスのインスタンスだな」と自動で判断し、実物の型をポロッと返してくれるんです。
—
4. 実務ではどう使うの?(ちょっと実践的な話)
「なるほど、仕組みは分かったけど、実際のWeb開発でどこで使うの?」と思いますよね。
例えば、UIライブラリやゲーム開発、あるいは複雑なプラグインシステムを作るときに、「クラスのコンストラクタを引数に取るヘルパー関数」を書くときによく使われます。
// 任意のクラスの設計図を受け取り、それをインスタンス化してログを出す関数
function createInstance
constructorClass: T
): InstanceType
console.log(“インスタンスを新しく生成します!”);
return new constructorClass();
}
// 先ほどの Receipt クラスを渡してみます
class UserProfile {
name: string = “初心者エンジニアさん”;
}
// userInstance の型は、自動的に UserProfile インスタンス型になります!
const userInstance = createInstance(UserProfile);
console.log(userInstance.name); // 「初心者エンジニアさん」
難しそうな型ガード (`T extends new (…args: any[]) => any`) が出てきてちょっとクラッときたかもしれませんが、大丈夫ですよ!
要するに、「クラスの設計図を受け取って、それから生まれる実物の型をそのまま返す便利な仕組み」として `InstanceType
—
最後に:一歩ずつ、確実に進んでいきましょう
TypeScriptのユーティリティ型は、最初は「呪文」のように見えて圧倒されてしまうこともあります。でも、ひとつひとつの型が「何をしてくれる道具なのか」を身近なものに例えて紐解いていけば、決して怖くありません。
`InstanceType
今日の記事が、あなたのTypeScript学習のモヤモヤを晴らす小さなきっかけになれたら、チーフアーキテクトとしてこれ以上嬉しいことはありません。
焦らず、自分のペースで楽しくコードを書いていきましょうね。応援しています!

コメント