TypeScriptにおける型ガードまとめ
はじめに
TypeScriptで開発を行う上で型の判定を行う場合が多々あります。 自分自身たまにどうすればよいか迷子になってしまうこともあるため備忘録としてまとめておきます。
概要
- プリミティブ型の判定:typeof
- プロパティ・メソッドの存在確認による判定:in
- クラスのインスタンスかどうかの確認による判定:instanceof
- オブジェクトに判別可能なプロパティを設けてそれで判断する:Descriminated Unions
typeof
プリミティブ型(string, number, boolean, undefined, null, symbol, bigint)を文字列で返却してくれるため、それを同値演算子(===)もしくは非同値演算子(!==)を使って判定を行います。
// a,b どちらかがstringなら文字列結合、numberなら足し算を行う const add = (a: string | number, b: string | number) => { if (typeof a === "string" || typeof b === "string") { // ここの部分 return a.toString() + b.toString(); } return a + b; };
in 演算子
〇〇がオブジェクトに存在するか確認することで型ガードを行う方法です。
type Foo = { name: string; age: number; } type Bar = { name: string; email: string; } type FooBar = Foo & Bar; const Baz: FooBar = (args: FooBar) => { console.log(args.name); if ("age" in args) { // argsにageプロパティがある場合 console.log(args.age); } };
instanceof 演算子
指定したクラスのインスタンスであるかどうかを判定させ、型ガードを行う方法です。 interfaceで定義した型の情報はJavaScriptにコンパイルされないため、この方法を使うことはできません。
class Foo { constructor(name, age) { this.name = name; this.age = age; } } class Bar { constructor(name, email) { this.name = name; this.email = email; } } const Fuga = new Foo("foo", 25); const Hoge = new Bar("bar", "test@example.com"); type Baz = Foo | Bar; const whatIsInstance = (arg: Baz) => { console.log(arg.name); if (arg instanceof Foo) console.log(arg.age); if (arg instanceof Bar) console.log(arg.email); };
Descriminated Unions
interface Bird { type: "Bird"; // ここが該当の箇所 flyingSpeed: number; } interface Dog { type: "Dog"; // ここが該当の箇所 runningSpeed: number; ] type Animal = Bird | Dog; const getSpeed = (animal: Animal) => { switch (animal.type) { case: "Bird": return animal.flyingSpeed; case: "Dog": return animal.runningSpeed; } }