TypeScriptのカスタム型ガード関数を作る方法を徹底解説!初心者でもわかる安全な型チェック
生徒
「TypeScriptで値がどんな型なのか安全に判断したいのですが、どうすればいいんですか?」
先生
「TypeScriptではカスタム型ガード関数を作ることで、値が特定の型かどうかを自分で判定できます。」
生徒
「typeof では判定できないオブジェクトの中身もチェックできますか?」
先生
「もちろんできます。型ガード関数は条件分岐やユニオン型と相性がよく、TypeScriptの型安全を上げるためにとても便利です。では基本から見ていきましょう。」
1. カスタム型ガード関数とは?
TypeScriptには、データの種類を判別するための便利な仕組みとして型ガード(Type Guard)があります。 型ガードとは、「この値はこの型ですよ」とTypeScriptに教えてあげるための仕組みのことです。 なかでも、開発者が独自に定義するものをカスタム型ガード関数と言います。
たとえば、変数が「文字列なのか?」「特定のプロパティを持つオブジェクトなのか?」といったことを確認しながら処理したい場面は多くあります。 カスタム型ガード関数を使うと、TypeScriptがその結果に基づいてコード補完やエラー検出を行ってくれるため、 プログラムをより安全に書くことができます。
型ガード関数には、戻り値としてvalue is 型という特別な書き方を使います。これは「この関数がtrueを返したら、その値はこの型だよ」とTypeScriptに教えるための構文です。
2. カスタム型ガードを作る基本構文
まず、カスタム型ガードの基礎となる構文を見てみましょう。ここでは、ある値が「文字列かどうか」を判定する単純な例を使います。
function isString(value: unknown): value is string {
return typeof value === "string";
}
const data: unknown = "Hello";
if (isString(data)) {
console.log(data.toUpperCase());
}
この例ではvalue is stringという記述がポイントです。もし関数がtrueを返せば、if文の中では、
dataが「必ず文字列である」とTypeScriptが判断してくれるため、文字列専用メソッドを安全に呼び出すことができます。
3. オブジェクト型をチェックする型ガード関数
次は、オブジェクトの型をチェックするもう少し実践的な例を見てみましょう。ユニオン型の変数から特定のオブジェクトだけを判別したい場合などに使われます。
ここではユーザー情報をあらわす型を例にします。
type User = {
name: string;
age: number;
};
function isUser(value: any): value is User {
return (
typeof value === "object" &&
value !== null &&
typeof value.name === "string" &&
typeof value.age === "number"
);
}
const item: unknown = { name: "Taro", age: 30 };
if (isUser(item)) {
console.log(item.name);
}
この型ガード関数は、名前と年齢のプロパティが両方存在し、型も正しいかをチェックしています。 TypeScriptの型推論はJavaScriptの実行時のチェックとは独立しているため、安全に扱うためにはこのような「実際の値の確認」が必要です。
4. カスタム型ガードでユニオン型を安全に扱う
カスタム型ガードの魅力は、ユニオン型との組み合わせで特に役立つことです。 ユニオン型は「AまたはB」など複数の型が混ざっているため、そのままではどの型に対して処理すべきかわかりません。
ここでは数値または文字列を受け取り、型ガードで安全に分岐させる例を紹介します。
function isNumber(value: unknown): value is number {
return typeof value === "number";
}
function printValue(value: string | number) {
if (isNumber(value)) {
console.log(value.toFixed(2));
} else {
console.log(value.toUpperCase());
}
}
printValue(42);
printValue("hello");
このように、型ガードを使うことで、TypeScriptが分岐ごとに適切な型を推論してくれるため、 エラーのない安全なコードが書けるようになります。特に複雑なユニオン型を扱う状況では欠かせない書き方です。
5. 型ガード関数の注意点とよくある失敗例
カスタム型ガードは便利ですが、注意しないと誤った判定をしてしまうことがあります。 初心者が特にやりがちなポイントを簡単にまとめてみます。
① プロパティの存在チェックだけでは不十分
オブジェクトにプロパティがあるかどうかだけでは、その型が正しいかどうか判断できない場合があります。 値の型までしっかり確認することが大切です。
② nullチェックを忘れる
typeof null === "object" となるため、nullが紛れ込んでいると誤判定の原因になります。
型ガード関数では必ず null の除外を行いましょう。
③ any を安易に使わない
anyは「何でもアリ」になる危険な型です。型ガードは unknown や混在型に対して使うことで効果が出るため、
むやみに any を使うのは避けましょう。
まとめ
カスタム型ガード関数を理解するとTypeScriptの安全性が一段上がる
この記事では、TypeScriptにおけるカスタム型ガード関数の作り方と考え方について、基礎から実践まで詳しく解説してきました。 カスタム型ガードとは、「この値は本当にこの型なのか?」という判断を、開発者自身が関数として定義し、 TypeScriptに明確に伝えるための仕組みです。 JavaScriptの柔軟さゆえに発生しがちな型の混乱を、TypeScriptの型システムと組み合わせて安全に制御できる点が最大の特徴です。
特に初心者の方は、typeofやinstanceofだけで型判定が完結すると考えがちですが、
実務ではオブジェクトの中身や、API・ユーザー入力のような「外部から来る不確かなデータ」を扱う場面が非常に多くあります。
そのような状況では、標準的な型チェックだけでは不十分であり、
カスタム型ガード関数を使って「どのプロパティが存在し、どの型なのか」を細かく確認する必要があります。
value is 型 という構文が持つ重要な役割
カスタム型ガード関数の最大のポイントは、戻り値の型として使われる value is 型 という特別な記法です。 これは単なる boolean を返す関数ではなく、 「この関数が true を返した場合、その値はこの型である」とTypeScriptに伝えるための宣言です。
この構文があることで、if 文や条件分岐の中では、 TypeScriptが自動的に型を狭めて(ナローイングして)くれます。 その結果、コード補完が正確になり、存在しないプロパティへのアクセスや、 型が合わないメソッド呼び出しをコンパイル時点で防げるようになります。 これは、規模が大きくなるほど効果を発揮する重要な仕組みです。
オブジェクト判定では「実行時チェック」が欠かせない
記事内で紹介したように、オブジェクト型のカスタム型ガードでは、 単にプロパティが存在するかどうかを見るだけでは不十分です。 そのプロパティの型そのものが正しいかまで確認することで、 はじめて安全な型チェックになります。
また、nullの存在を必ず除外する点も重要です。
JavaScriptの仕様上、typeof null === "object"となるため、
nullチェックを忘れると、意図しないデータを正しいオブジェクトとして扱ってしまう危険があります。
カスタム型ガード関数は「安全の最後の砦」になることが多いため、
実装時には慎重さが求められます。
ユニオン型と組み合わせることで真価を発揮する
カスタム型ガード関数が特に力を発揮するのが、ユニオン型と組み合わせた場合です。 ユニオン型は柔軟で便利な一方、そのままではどの型として扱えばよいか判断できません。 そこで型ガードを使って分岐させることで、処理ごとに適切な型を安全に扱えるようになります。
数値と文字列、複数のオブジェクト型、タグ付きユニオンなど、 実務でよくあるケースほど、カスタム型ガードの恩恵は大きくなります。 「型エラーを避けるため」だけでなく、 「コードの意図を明確に伝えるため」にも型ガードは非常に有効です。
サンプルで振り返るカスタム型ガードの基本形
type Product = {
id: number;
name: string;
};
function isProduct(value: unknown): value is Product {
return (
typeof value === "object" &&
value !== null &&
typeof (value as any).id === "number" &&
typeof (value as any).name === "string"
);
}
const data: unknown = { id: 1, name: "Notebook" };
if (isProduct(data)) {
console.log(data.name);
}
このように、unknown型から始めてカスタム型ガードで判定する流れは、 外部データを扱う場面で非常に安全です。 TypeScriptは静的型付け言語ですが、実行時の値までは保証してくれません。 そのギャップを埋めるのが、カスタム型ガード関数の役割です。
型ガードを使いこなすことが成長への近道
カスタム型ガード関数を正しく使えるようになると、 TypeScriptで書くコードの信頼性は大きく向上します。 初心者のうちは少し難しく感じるかもしれませんが、 「値を疑う」「必ずチェックする」という意識を持つことが、 バグを減らし、読みやすいコードを書く第一歩になります。
今回学んだ考え方は、APIレスポンスの検証、ユーザー入力チェック、 大規模アプリケーションのデータ管理など、さまざまな場面で活用できます。 TypeScriptの型安全を最大限に活かすためにも、 カスタム型ガード関数はぜひ身につけておきたい重要スキルです。
生徒
「型ガードって難しそうでしたが、自分で安全確認の関数を作れるのは便利ですね。」
先生
「そうですね。TypeScriptは“型を書くだけ”ではなく、“型を守る仕組み”まで作れるのが強みです。」
生徒
「value is 型 という書き方が、TypeScriptに伝える合図なんですね。」
先生
「その理解はとても大切です。型ガードはTypeScriptとの会話のようなものですよ。」
生徒
「これからは unknown 型と型ガードをセットで使ってみます。」
先生
「それができれば安心です。安全な型チェックを積み重ねていきましょう。」