TypeScriptの世界へようこそ!チーフアーキテクトの私です。
「よし、TypeScriptを書くぞ!」と意気込んでコードを書き始めたものの、赤色の波線(型エラー)に阻まれて、「なんだこれ、動かないじゃないか……」と頭を抱えてしまった経験、ありませんか? 大丈夫です、最初はみんなそこを通ります。私も昔はよくエラーと睨めっこしてコーヒーを飲んでいました。
TypeScriptの最大の魅力であり、時に厳しく立ちはだかる壁が「型(かた)」の存在です。JavaScriptのノリで自由に書きたいのに、TypeScriptは「おいおい、ここは文字列なのか数値なのかハッキリしてくれよ!」と聞いてきます。
今回は、そんなTypeScriptの厳しさとうまく付き合うための第一歩、「等価性チェックによる型ガード」についてお話しします。お買い物のレジでのやり取りをイメージしながら、肩の力を抜いて一緒に見ていきましょう!
—
1. 型ガードってなに? 身近な例えでお話します
突然ですが、大きなおもちゃ箱を想像してください。
その中には、プラスチックのブロックもあれば、柔らかいぬいぐるみも、お菓子もごちゃ混ぜに入っています。
あなたがいま、「硬いブロックで遊びたい!」と思ったとき、おもちゃ箱から手探りで掴んだものが、もしぬいぐるみだったら……「これじゃない!」ってなりますよね。
プログラムの世界もこれとまったく同じです。
変数の中に「文字」が入っているのか、「数字」が入っているのか、あるいは「本当になんにもない(nullなど)」のか分からない状態のまま、突然「文字を大文字にする処理をして!」と命令すると、プログラムはパニックを起こしてエラーを出してしまいます。
そこで登場するのが「型ガード(Type Guard)」です。
これは、おもちゃ箱から取り出したものに対して、「君、本当にブロックかい?」と事前にチェックする門番のようなもの。
なかでも、一番シンプルで強力なのが、普段のJavaScriptでもよく使う `===` や `!==` といった等価性チェック(中身が同じかどうかの比較)を使った型ガードです。
—
2. 実際にコードを書いてみよう!
百聞は一見に如かず。実際にエディタを開いたつもりで、コードを見てみましょう。
ここでは、「画面に表示するメッセージ」を扱う場面を想像してください。このメッセージは、文字(string)のときもあれば、まだ読み込み中だから「loading」という特定の文字、あるいは何もない(null)かもしれません。
// メッセージの型を定義します(いろんな可能性が混ざっている状態)
type MessageState = string | “loading” | null;
function displayMessage(message: MessageState) {
// ここで等価性チェック(===)を使います!
// パターン1: “loading” と完全に一致するか?
if (message === “loading”) {
// TypeScriptはこの中に入った瞬間、「この message は絶対に ‘loading’ だな」と理解します
console.log(“データを一生懸命読み込んでいます…少々お待ちください!”);
return;
}
// パターン2: null と一致するか?
if (message === null) {
// ここに入った瞬間、message は null だと確定します
console.log(“表示するメッセージはありません。”);
return;
}
// パターン3: 上記のチェックをすべてすり抜けたもの
// ここに到達した時点で、message は必ず通常の「文字列(string)」に絞り込まれています!
// だから、安心して文字列専用の機能(文字の長さを測る .length など)が使えます
console.log(`メッセージの長さは ${message.length} 文字です。`);
console.log(`内容: ${message}`);
}
どうでしょう? `if (message === “loading”)` や `if (message === null)` という、普段私たちが何気なく書いている条件分岐が、そのままTypeScriptへの「あ、ここから先はこういうデータ型になるからね」というサイン(型ガード)になっているんです。
特になんの難しい呪文も使っていませんよね。これなら今日からすぐに実務で使えそうです。
—
3. つまずきやすいポイントと「大丈夫ですよ」のフォロー
ここで、初心者の人がよくハマる「落とし穴」を一つだけシェアしておきます。
落とし穴:「あれ、絞り込めてない……?」
たまに、次のようなコードで「なんでエラーになるの!?」と悩む人がいます。
function processValue(value: string | number) {
// 「文字か数字のどちらかだけど、たぶん文字だろう」となんとなく処理しようとする
// エラー:Property ‘toUpperCase’ does not exist on type ‘string | number’.
console.log(value.toUpperCase());
}
TypeScriptは優柔不断な状態(文字か数字か分からない状態)のとき、どちらの専用機能も使わせてくれません。「安全性が確認できるまでは、危ないから触っちゃダメ!」という親心です。
解決策
ここでも今回のテーマである等価性チェックや、後々学ぶ `typeof` などを使って、「いま君はどのタイプ?」と明示してあげる必要があります。
function processValue(value: string | number) {
// もし型が string なら…とチェックする(※ここでは typeof を使っていますが基本は一緒です)
if (typeof value === “string”) {
// これで TypeScript も安心!
console.log(value.toUpperCase());
} else {
// こっちは自動的に number に絞り込まれます
console.log(value.toFixed(2));
}
}
「エラーが出た=TypeScriptに嫌われている」ではなく、「あ、まだ型が確定してなくて心配してくれているんだな」と捉えてあげてください。等価性チェック(`===`)を使って「これと一緒だよね?」と教えてあげるだけで、TypeScriptは急に優しく「それなら安心だね!」と許可を出してくれます。
—
4. まとめ:焦らず、一歩ずつ進んでいきましょう
今回は、等価性チェック(`===` や `!==`)を使った型ガードの基本についてお話ししました。
- 型ガードとは?:ごちゃ混ぜのデータの中から、「これだよね?」と特定の種類に絞り込むテクニック。
- 等価性チェック:`if (value === “特定の値”)` と書くだけで、TypeScriptが自動的に型を安全に理解してくれる。
- エラーが出ても大丈夫:それはTypeScriptがあなたのコードの安全を守ろうとしてくれている証拠。
最初から完璧に型を使いこなせる人なんていません。現場のプロたちも、日々「おっと、ここで型が合わないな」と独り言をつぶやきながらコードを書いています。
まずは、身近な条件分岐を書くときに、「あ、この `===` のおかげでTypeScriptが安心してるんだな」ということを片隅に置きながら、楽しくコードを書いてみてくださいね。あなたのTypeScriptライフを、シニアアーキテクトとしてこれからも応援しています!

コメント