この記事では TypeScript の型ガードについて、分かりやすく具体的なコード例とともに解説していきます。
まず、型ガードとは TypeScript の便利な機能の1つで 特定の型に属する変数を安全 に扱う方法です。
型ガードは特定の型が期待される場所で実際にその型が利用されているかどうかを判断することができます。
実際のコードを見ていきましょう!
function isString(value: any): value is string {
return typeof value === "string";
}
let value: any = "Hello, TypeScript!";
if (isString(value)) {
console.log(value.toUpperCase()); // HELLO, TYPESCRIPT!
}
上記のコードでは isString
関数が型ガードの役割を果たしています。
value
が string
型であることを確認した後、安全に toUpperCase
メソッドを実行しています。
「TypeScript の型ガードがどんなものかわかったけど、どうして必要になるんだろう?」
次はそんな疑問に対して、なぜ型ガードが必要なのかを解説していきます。
型ガードを使うことで 型エラーを事前に防ぐことができる ため、コードが安全かつ堅牢になります。
そのため、TypeScript の 強力な型システムを最大限活用 するために型ガードが重要になってきます。
function printLength(value: string | number) {
if (typeof value === "string") {
console.log(value.length); // 文字列の場合、length を出力
} else {
console.log(value); // 数値の場合、そのまま出力
}
}
printLength("Hello, TypeScript!"); // 18
printLength(42); // 42
上記の例では printLength
関数は string
型と number
型のどちらも受け取れますが、型ガードを使って渡された型に対しての適切な処理を行っています。
TypeScript にはいくつかの組み込み型ガードがあり、その中でも最も基本的なものが 組み込みの型ガード と呼ばれるものです!
組み込みの型ガードの代表的なものには typeof
や instanceof
があります。
typeof
は、変数のデータ型を判断するための機能です。
主にプリミティブ型と呼ばれる基本的な型(string
、number
、boolean
、symbol
、bigint
、undefined
、object
)を判定する際に使用されます。
以下の例を見てみましょう!
function getType(value: string | number) {
if (typeof value === "string") {
console.log("This is a string!");
} else {
console.log("This is a number!");
}
}
getType("Hello, TypeScript!"); // This is a string!
getType(42); // This is a number!
上記のコードでは getType
関数は string
型と number
型のどちらも受け取れますが、typeof
を使って引数に応じて適切な処理を行っています。
instanceof
は、オブジェクトが特定のクラスのインスタンスであるかどうかを判断する機能です。
基本的にはクラスやインターフェースを使ったカスタム型の判定に使用されます。
実際のコードを見てみましょう。
class Person {
constructor(public name: string) {}
}
class Animal {
constructor(public species: string) {}
}
function printInfo(value: Person | Animal) {
if (value instanceof Person) {
console.log(`こんにちは、 ${value.name}!`);
} else {
console.log(`これは ${value.species} です`);
}
}
printInfo(new Person("ジョン")); // こんにちは、ジョン!
printInfo(new Animal("犬")); // これは 犬 です
printInfo
関数は Person
型と Animal
型のどちらも受け取れますが、引数である instanceof
を使って適切な処理を行っています。
このように、組み込み型ガードを使うと型安全なコードを簡単に実現できます。
これらの機能は TypeScript の型システムを活用して、より優れたコードを書くために大事なのでぜひ覚えておきましょう!
型ガードを使っていると、自分で定義した型に対して型ガード を使いたくなる場面が多々あります。
そんなときに使えるカスタム型に型ガードを適用する方法を見ていきましょう。
自分が定義した型に対する型ガードは value is Type
の形式を持つ関数を定義することで実現できます。
interface Circle {
kind: "circle";
radius: number;
}
interface Square {
kind: "square";
sideLength: number;
}
type Shape = Circle | Square;
function isCircle(shape: Shape): shape is Circle {
return shape.kind === "circle";
}
function getArea(shape: Shape) {
if (isCircle(shape)) {
return Math.PI * shape.radius ** 2;
} else {
return shape.sideLength ** 2;
}
}
const circle: Circle = { kind: "circle", radius: 5 };
const square: Square = { kind: "square", sideLength: 4 };
console.log(getArea(circle)); // 78.53981633974483
console.log(getArea(square)); // 16
上記のコードでは Shape
型を Circle
型と Square
型のどちらも入る型として定義しています。
これに対して getArea
関数を実行し、その中で引数として渡されたのが Circle
型と Square
どちらかを判断して処理の内容を変更しています。
このときに isCircle
関数を使って、shape.kind === "circle"
の条件に一致するものは Circle
型である、とすることで型ガードを実現しています。
最後に、より実践的な型ガードの例として API のレスポンスを安全に処理する方法を紹介します!
interface ApiResponse {
status: number;
data?: any;
error?: string;
}
function isSuccess(response: ApiResponse): response is ApiResponse & { data: any } {
return response.status >= 200 && response.status < 300;
}
function handleError(response: ApiResponse) {
if (isSuccess(response)) {
console.log("Success!", response.data);
} else {
console.error("Error:", response.error);
}
}
const successResponse: ApiResponse = { status: 200, data: { message: "Success!" } };
const errorResponse: ApiResponse = { status: 500, error: "Internal Server Error" };
handleError(successResponse); // Success! { message: 'Success!' }
handleError(errorResponse); // Error: Internal Server Error
まず、ApiResponse
インターフェースを定義して、API レスポンスの形状を表現しています。status
プロパティは HTTP ステータスコードを表していて、成功時には data
プロパティが、失敗時には error
プロパティが存在します。
次に isSuccess
関数を定義しています。
この関数は引数として ApiResponse
型の値を受け受け取って、そのレスポンスが成功かどうかを判断する型ガードです。
HTTP ステータスコードが 200
以上 300
未満の場合に成功と判断して、data
プロパティの存在が保証されています。
最後に handleError
関数を定義しています。
この関数は isSuccess
関数を使って引数として渡された ApiResponse
型の値が成功かどうかを判断してそれに応じて適切な処理を行います。
成功時には Success!
と data
を出力し、失敗時には Error: と error
を出力します。
この実践的な例では、型ガードを使うことで API レスポンスを安全に処理してコードの品質を向上させています!
このように型ガードを使うことで、より型安全なコードを書くことができるためバグの発生を抑えることができます。
ぜひ実践的なコードに型ガードを活用してみてください!
TypeScriptの短絡評価の使い方「&&」「||」「??」の解説
TypeScriptのタイマー関数setTimeoutとsetIntervalの使い方
TypeScriptの多次元配列の使い方についてわかりやすく解説
TypeScriptでのタプルの使い方と実践テクニックを解説
TypeScriptのimport typeをわかりやすく解説
TypeScriptの配列やオブジェクトのソート完全ガイド
TypeScriptコメントアウトの使い方 完全ガイド
TypeScriptのオブジェクトとプロパティの存在チェック完全ガイド
TypeScriptで即時関数を使う方法を解説!基本から実践的な使い方まで