TypeScriptで型ガード(Type Guard)を使う基本方法
生徒
「先生、TypeScriptで変数の型を条件で判定する方法ってありますか?」
先生
「とても良い質問ですね。TypeScriptには『型ガード(Type Guard)』という仕組みがあって、条件分岐の中で変数の型を特定できるんですよ。」
生徒
「型を特定するって、どういうことですか?型って最初に決まってるんじゃないんですか?」
先生
「いい質問ですね。ユニオン型のように、複数の型を持つ変数のときに、その中のどの型なのかを判断する必要があるんです。型ガードを使えば、安全に型を絞り込むことができます。」
生徒
「なるほど!それでは、実際に使い方を教えてください!」
先生
「もちろんです。まずは基本的な型ガードの使い方を見ていきましょう。」
1. 型ガード(Type Guard)とは?
TypeScriptの型ガード(Type Guard)とは、プログラムの中で「変数がどの型なのか」を判断する仕組みのことです。特に、ユニオン型(複数の型が混ざった型)を使っているときに役立ちます。
たとえば、ある変数が「文字列(string)」か「数値(number)」のどちらかの場合、型ガードを使えば安全にその型を判別して、正しい処理を実行することができます。
TypeScriptでは、型ガードを使うことで、コンパイル時に型が明確になるため、実行時のエラーを減らすことができます。
2. typeofを使った型ガードの基本
もっともよく使われる型ガードがtypeof演算子を使う方法です。これは、変数の型が「string」や「number」などの基本型(プリミティブ型)かどうかを判定するために使います。
function printValue(value: string | number) {
if (typeof value === "string") {
console.log("文字列の長さは", value.length, "です");
} else {
console.log("数値の2倍は", value * 2, "です");
}
}
printValue("TypeScript");
printValue(10);
文字列の長さは 10 です
数値の2倍は 20 です
typeofを使うと、if文の中で自動的に型が絞り込まれ、TypeScriptが「このブロックではvalueは文字列」「このブロックでは数値」と理解してくれます。
3. instanceofを使った型ガード
instanceofは、オブジェクトが特定のクラスから生成されたものかを判定するための型ガードです。クラスとは、オブジェクトを作るための設計図のようなものです。
class Dog {
bark() {
console.log("ワンワン!");
}
}
class Cat {
meow() {
console.log("ニャー!");
}
}
function makeSound(animal: Dog | Cat) {
if (animal instanceof Dog) {
animal.bark();
} else {
animal.meow();
}
}
makeSound(new Dog());
makeSound(new Cat());
ワンワン!
ニャー!
このように、instanceofを使うと、オブジェクトがどのクラスから作られたのかを安全に判断することができます。
4. in演算子を使った型ガード
in演算子を使えば、「オブジェクトの中に特定のプロパティ(変数のようなもの)が存在するかどうか」で型を判断できます。複数の型が似た構造をしているときに便利です。
type Car = {
drive: () => void;
};
type Plane = {
fly: () => void;
};
function move(vehicle: Car | Plane) {
if ("fly" in vehicle) {
vehicle.fly();
} else {
vehicle.drive();
}
}
move({ drive: () => console.log("車が走っています") });
move({ fly: () => console.log("飛行機が飛んでいます") });
車が走っています
飛行機が飛んでいます
このように、in演算子でプロパティの有無を調べることで、オブジェクトの型を安全に区別できます。
5. ユーザー定義型ガード(is句)の使い方
TypeScriptでは、自分で型ガードを定義することもできます。これをユーザー定義型ガードと呼びます。関数の戻り値にvalue is 型という形を使うことで、特定の型であることを明示できます。
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
function move(pet: Fish | Bird) {
if (isFish(pet)) {
pet.swim();
} else {
pet.fly();
}
}
move({ swim: () => console.log("魚が泳いでいます") });
move({ fly: () => console.log("鳥が飛んでいます") });
魚が泳いでいます
鳥が飛んでいます
このように自分で型ガードを作っておくと、複雑な型の判定も簡単に書けるようになります。pet is Fishという書き方は、「もしこの関数がtrueを返したらpetはFish型ですよ」という意味です。
6. 型ガードを使うメリット
型ガードを使うと、TypeScriptが変数の型を正確に理解してくれるため、型エラーが減り、安心してコードを書けます。また、開発中にエディタが自動補完してくれるので、どんなプロパティやメソッドが使えるのかもすぐ分かります。
もし型ガードを使わずに書くと、「プロパティが存在しません」といったエラーが出やすくなります。型ガードを使うことで、より安全で読みやすいコードを書くことができます。
まとめ
TypeScriptでの型ガードは、プログラムを安全にし、変数の型を明確にするための重要なテクニックです。typeofやinstanceof、in演算子、そしてユーザー定義型ガード(is句)を活用することで、ユニオン型や複雑なオブジェクトの型を安全に判別できます。初心者がつまずきやすい「プロパティが存在しない」「型が違う」というエラーを防ぎ、実行時のバグを減らすことが可能です。
例えば、文字列と数値が混在する変数に対してtypeofで型を確認するだけで、型が絞り込まれ、文字列用の処理や数値用の処理を安全に書くことができます。オブジェクトやクラスを扱う場合はinstanceofを使うことで、どのクラスのインスタンスかを安全に判断できます。さらに、オブジェクトの特定のプロパティが存在するかで型を判断するin演算子や、カスタム型ガードを使うことで、より複雑な型判定も簡単に書けるようになります。
サンプルコード:複数の型ガードの併用例
type Dog = { bark: () => void };
type Cat = { meow: () => void };
function isDog(pet: Dog | Cat): pet is Dog {
return (pet as Dog).bark !== undefined;
}
function makeSound(pet: Dog | Cat) {
if (isDog(pet)) {
pet.bark();
} else if ("meow" in pet) {
pet.meow();
} else {
console.log("不明な動物です");
}
}
makeSound({ bark: () => console.log("ワンワン!") });
makeSound({ meow: () => console.log("ニャー!") });
この例では、ユーザー定義型ガードとin演算子を組み合わせることで、複雑な型判定でも安全に処理を分岐できます。TypeScriptが型を正しく理解するため、誤ったメソッドの呼び出しを防ぎ、開発効率も向上します。
型ガードを意識的に使うことで、コードの可読性と保守性が大きく向上します。開発チームでコードを共有する際にも、変数がどの型であるか明確になるため、レビューやバグ修正がスムーズに行えます。初心者でもまずはtypeofやinstanceofから始め、徐々にユーザー定義型ガードやin演算子を使いこなすと良いでしょう。
生徒
「先生、typeofやinstanceof、in演算子、ユーザー定義型ガードまで学ぶと、型を安全に判断できることがよく分かりました!」
先生
「その通りです。これらを組み合わせることで、ユニオン型や複雑なオブジェクトでも安全に型を絞り込めます。TypeScriptの型安全性を最大限に活かすためにとても役立つテクニックです。」
生徒
「型ガードを使うと、開発中に型エラーが減り、コードの読みやすさも上がるんですね。実際に書いてみると、安心して関数やオブジェクトを操作できる感じがします。」
先生
「その通りです。まずは基本のtypeofやinstanceofから始めて、慣れてきたらカスタム型ガードやin演算子を使うとさらに柔軟で安全なコードが書けるようになります。これをマスターすれば、TypeScriptの強みである型安全な開発がしっかり活かせます。」