typeofの概要
| データ型の判定 JavaScript演算子 | ||
|
typeof 概要 わかりやすく説明
|
||
|
typeofの基本的な使い方
typeof が返す文字列は、完全に小文字で統一されています。実際の各データ型に対する評価結果は以下の通りです。
// 1. プリミティブデータ型の判定
console.log(typeof "Hello"); // 出力: "string"
console.log(typeof 42); // 出力: "number"
console.log(typeof true); // 出力: "boolean"
console.log(typeof undefined); // 出力: "undefined"
console.log(typeof Symbol("id"));// 出力: "symbol" (ES2015以降)
console.log(typeof 10n); // 出力: "bigint" (ES2020以降)
// 2. 構造化・参照データ型の判定
console.log(typeof {}); // 出力: "object"
console.log(typeof []); // 出力: "object" (⚠️配列もオブジェクトの一種とみなされる)
console.log(typeof function() {}); // 出力: "function" (構造上はオブジェクトだが個別に識別される)
// 3. 特殊なケース
console.log(typeof null); // 出力: "object" (⚠️仕様上の歴史的なバグ)
- 文字列、数値、真偽値などの基本プリミティブ型は直感通りの文字列が返ります。
- 関数(
Function)はオブジェクトの一種ですが、typeofは特別に"function"という独自の文字列を返してくれるため、コールバック関数の安全チェックに非常に便利です。
typeofの応用例(関数の引数チェックと多態的な処理)
受け取る引数の型によって処理を柔軟に切り替える(ポリモーフィズム的な)防衛コーディングのパターンです。
// 引数の型に応じてフォーマットを柔軟に切り替える関数
function formatPadding(value) {
// 文字列が渡されたらそのまま両端をスペースで囲う
if (typeof value === "string") {
return `[ ${value.trim()} ]`;
}
// 数値が渡されたら指定された文字数のスペースを生成する
if (typeof value === "number") {
return " ".repeat(value);
}
// それ以外の予期せぬ型はエラーとして弾く
throw new TypeError("引数には文字列または数値を指定してください。");
}
console.log(formatPadding("Welcome")); // 出力: "[ Welcome ]"
console.log(formatPadding(4).length); // 出力: 4 (4文字分の空白スペース)
// formatPadding(true); // 🛑 TypeErrorが発生しバグを早期検知
注意点
typeof nullが"object"になる歴史的バグ: JavaScriptの最初の実装におけるメモリ上のデータ表現(型タグの割り当て)のバグが原因で、nullの判定結果が"object"になってしまいます。この挙動はすでに数多くの既存Webサイトのコードに埋め込まれてしまっているため、互換性を崩さないよう、現在も仕様としてあえて修正されずに残されています。// ⚠️ nullを安全にチェックするための正しい防衛コード const targetData = null; if (targetData && typeof targetData === "object") { // ⭕ targetDataが「nullではなく」、かつ本物のオブジェクトである場合のみ通る console.log("安全にオブジェクトのプロパティにアクセスできます。"); } else { console.log("データは空、またはオブジェクトではありません。"); // こちらが実行される }- 配列(Array)を識別できない問題:
typeof []は単に"object"を返すため、通常のオブジェクト({})と配列を区別できません。配列かどうかを正確に知りたい場合は、ES5で追加された専用静的メソッドArray.isArray()を使用します。// ⚠️ 配列の識別ミスを防ぐアプローチ const list = [1, 2, 3]; console.log(typeof list === "object"); // true ❌ これでは普通のオブジェクトか配列か分からない console.log(Array.isArray(list)); // true ⭕ 配列であることを100%確実に特定 NaN(Not-a-Number)の型評価: 計算エラーなどで発生するNaN(非数)に対しtypeofを実行すると、文字通り「数値ではない」という名前のステータスであるにもかかわらず、データ型としては"number"が返ってきます。// ⚠️ NaNの型チェックに潜む罠と対策 const invalidResult = 10 / "文字列"; // 計算不能で NaN になる console.log(typeof invalidResult); // "number" ❌ 数値として判定されてしまう console.log(Number.isNaN(invalidResult)); // true ⭕ 本当に有効な数値データか安全に判定
よくある質問
- Q:
typeof演算子を使用するとき、後ろの対象を括弧で囲むtypeof(value)と、スペースで区切るtypeof valueに機能的な違いはありますか? - A: 機能やパフォーマンス上の違いは一切ありません。JavaScriptにおいて
typeofは関数ではなく「演算子」であるため、スペースで区切るtypeof valueが本来のスマートな書き方です。
ただし、特定の計算式の「計算結果の型」を判定したい場合は、演算の優先順位を明確にするために括弧で囲む必要があります。// 括弧が必要になる応用パターン console.log(typeof "Hello" + 10); // 出力: "string10" ❌ (typeof "Hello" が先に評価され、文字列結合される) console.log(typeof ("Hello" + 10)); // 出力: "string" ⭕ (計算した結果全体の型を安全に判定) - Q: クラスから生成したカスタムインスタンスの型(どのクラス由来か)を
typeofで特定することはできますか? - A: できません。自作したクラスや組み込みのクラス(
Dateや `RegExp` など)から生成されたインスタンスは、`typeof` を通すと一律で"object"に丸められてしまいます。
インスタンスの具体的な生成元(由来クラス)を特定・検証したい場合は、`typeof` ではなく **instanceof演算子** を使用してください。// クラスインスタンスの正確な判定コード例 class User {} const admin = new User(); console.log(typeof admin); // "object" ❌ クラス名までは判別できない console.log(admin instanceof User); // true ⭕ Userクラスのインスタンスであることを正確に証明
まとめ
typeof演算子は、変数が保持している現在の生データ型を文字列として取り出し、柔軟なランタイムチェックを行うための最も軽量なインスペクション命令です。
- 文字列、数値、関数といった主要なプリミティブ型や実行可能オブジェクトを瞬時に見分ける用途に最適です。
nullが"object"を返すバグや、配列・NaNの誤認リスクといった言語仕様上の境界条件を正確に把握し、必要に応じてArray.isArray()などの専門APIを織り交ぜて防衛してください。- 判定結果の文字列はすべて「完全小文字(例:
"string")」で返却されるため、タイポによる条件分岐のすり抜けが起きないよう厳密等価演算子(===)を用いた手堅い比較を心がけましょう。