【入門編】 InstanceTypeによるインスタンス型の取得 – TypeScript実践ガイド

こんにちは!TypeScriptの世界へようこそ。チーフアーキテクトの私です。

TypeScriptを書き始めると、「string」や「number」といった基本の型から、少しずつ「型、なんだか難しくなってきたぞ……?」という壁にぶつかる瞬間がありますよね。特に、クラス(Class)や「コンストラクタ」という言葉が出てくると、途端にコードが難解に感じられて、そっとエディタを閉じたくなる気持ち、痛いほどよく分かります。

大丈夫ですよ、安心してください。今日はそのモヤモヤをスッキリ解消するために、`InstanceType` という、ちょっと名前はかっこいいけれど、実は私たちの強い味方になってくれる魔法の道具についてお話しします。

身近な例え話をたっぷり交えながら、一緒に紐解いていきましょう!

—

1. クラスって「設計図」、インスタンスは「そこから作られた実物」

まずは、`InstanceType` を理解するための大切な前提をおさらいしましょう。

皆さんは、街で見かける「自動販売機」を思い浮かべてみてください。
あの頑丈な金属の箱を何台も並べて作るために、メーカーには「自動販売機の設計図」がありますよね。

  • クラス(Class) = 自動販売機の「設計図」
  • インスタンス(Instance) = その設計図通りに工場で作られて、実際に街角に置かれた「本物の自動販売機」

TypeScriptでコードを書くとき、私たちはよく「設計図(クラス)」を用意して、そこから「実物(インスタンス)」を作ります。

// 自動販売機の「設計図(クラス)」
class VendingMachine {
// 中に入っているジュースの数
juiceCount: number = 10;

// ボタンを押してジュースを買う機能
buyJuice() {
console.log(“ガチャン!ジュースが出てきました。”);
}
}

// 設計図から、実物(インスタンス)を「new」という合言葉で作る!
const myMachine = new VendingMachine();

ここで、`myMachine` という変数には、「設計図(VendingMachine)をもとに作られた実物」が入っています。この実物の型を、TypeScriptはちゃんと自動で察知してくれます。ここまでは何てことないですよね。

—

2. 「設計図そのもの」を渡されたとき、どう困る?

さて、ここからが本題です。
もし、誰かから「この設計図(クラスそのもの)をあげるから、ここから作られる実物の型を教えて!」と言われたら、どうでしょう?

ちょっとややこしい話をしますね。TypeScriptにおいて、「設計図そのもの(クラスのコンストラクタ)」を表す型は、実物の型とは違います。

// VendingMachineという「設計図そのもの」を表す型は、こう書きます
let MachineConstructor: typeof VendingMachine = VendingMachine;

「あれ? `VendingMachine` って書けばいいんじゃないの?」と思った方、大正解です。通常はそこまで意識しなくても動いてくれます。

しかし、「関数にクラスの設計図をポンと渡して、その中でうまいことインスタンスを操作したい」という、ちょっと高度なことをやろうとすると話が変わってきます。設計図そのものの型 (`typeof VendingMachine`) と、実物の型 (`VendingMachine`) は別物なので、「この設計図から生まれる実物の型って、一体なんだっけ?」とTypeScriptが迷子になってしまうことがあるんです。

そんなとき、「この設計図を渡すから、そこから生まれる実物の型を教えてちょうだい!」とTypeScriptにお願いできる魔法のアイテムが、`InstanceType` なのです。

—

3. InstanceType って、なにをしてくれるの?

`InstanceType` の正体は、TypeScriptが用意してくれている「型を変換する便利な道具(ユーティリティ型)」の一つです。

英語のニュアンスそのままなのですが、こう読んでみてください。

> 「InstanceType(インスタンスの型を) (渡された設計図から)取り出す!」

お買い物に例えるなら、「カタログ(設計図)の表紙を見せるだけで、倉庫からその製品の実物(インスタンス)を取り出して見せてくれる自動お取り寄せシステム」のようなものです。

百聞は一見に如かず。実際にコードを見てみましょう。

// 1. まずは普通のクラス(設計図)を用意
class Dog {
bark() {
console.log(“ワン!”);
}
}

// 2. 「Dogの設計図そのもの」を型として変数に入れます
type DogConstructor = typeof Dog;

// 3. ここで登場するのが InstanceType!
// 「DogConstructor(設計図)から生まれる実物の型って何?」と聞いています。
type MyDogInstance = InstanceType;

// 結果として、 MyDogInstance は 「Dog」 という実物の型と同じ意味になります!
const pochi: MyDogInstance = new Dog(); // バッチリ型が合います!
pochi.bark(); // 「ワン!」

「おぉ……なんだかカッコいいけど、これっていつ使うの?」と思いましたか?
そうですね、普段のアプリ開発で、自分で書いたクラスをその場で `new` するだけなら、実はあまり使いません。

真価を発揮するのは、「動的にクラスを受け取る関数」を書くときです。

—

4. 実戦投入!動的にクラスを扱う関数を作ってみよう

例えば、「どんなクラスの設計図でも受け取って、それを新しく画面に生み出す(インスタンス化する)工場のような関数」を作りたいとします。

こんな時、`InstanceType` がないと、型の指定にすごく苦労します。でも、これを知っていればスマートに書けます。

// 従業員を表すクラス
class Employee {
constructor(public name: string) {}
}

// ロボットを表すクラス
class Robot {
constructor(public serialNumber: string) {}
}

/

  • 【工場の関数】
  • どんな「設計図(T)」を受け取っても、
  • InstanceType を使って「正しい実物の型」を返り値の型として保証する!

/
function createInstance any>(
ctor: T
): InstanceType {
// ※複雑に見えますが、「どんな引数でも受け取れるコンストラクタ」という意味です

// 実際に new して返す
// (※ここでは分かりやすくするため、簡易的に any でキャストしています)
return new ctor(“適当なデータ”) as InstanceType;
}

// さあ、使ってみましょう!
// Employeeの設計図を渡すと……
const worker = createInstance(Employee);
// worker の型は、自動的に 「Employee」 になります!
console.log(worker.name); // 「適当なデータ」

// Robotの設計図を渡すと……
const android = createInstance(Robot);
// android の型は、自動的に 「Robot」 になります!
console.log(android.serialNumber); // 「適当なデータ」

お疲れ様でした!少し難しい構文 (`new (…args: any[]) => any` など) も出てきましたが、一番大切なポイントはそこではありません。

> 「クラスの設計図(コンストラクタ)を引数で受け取るような汎用的なコードを書くとき、そこから作られる実物の型を知りたければ `InstanceType` を使えば一発で解決する」

これさえ心に留めておいてもらえれば、100点満点です!

—

まとめ:つまずいたときは「設計図と実物」を思い出して

TypeScriptの高度な型機能は、最初は呪文のように見えて心が折れそうになりますよね。「なんでこんな面倒なことしなきゃいけないんだろう」と思うこともあるでしょう。

でも、それはTypeScriptが「あなたの書いたコードの安全性を、一生懸命後ろから支えようとしてくれているから」なんです。

  • クラスは「設計図」
  • インスタンスは「実物」
  • `InstanceType` は、設計図から実物の型を引っ張り出す「お取り寄せボタン」

このイメージさえ持っておけば、今後もっと複雑なライブラリのコードや、フレームワークの内部構造を読むときにも、きっと「あ、あのときの仕組みだな」とスッと理解できるようになります。

一歩ずつ、自分のペースでTypeScriptと仲良くなっていきましょう。あなたの開発ライフが少しでも楽しく、快適になりますように!チーフアーキテクトの私でした。また次回の記事でお会いしましょう!

コメント

タイトルとURLをコピーしました