【JavaScript】型を確認する方法を初心者向けにわかりやすく解説

はじめに

JavaScriptを学び始めると、データの「型」について戸惑う場面があるかもしれませんね。
数値や文字列だけでなく、配列やオブジェクトなどさまざまなデータを扱えるのがJavaScriptの特徴です。
しかし、実際の開発では「この変数は数値なのか文字列なのか、それともオブジェクトなのか」を正確に把握しておく必要があります。
曖昧なまま進めると、想定外の挙動やエラーの原因になりやすいからです。
そこで、この記事ではJavaScriptの型を確認するための基本的な方法を、初心者の皆さんにもわかりやすく紹介していきます。

この記事を読むとわかること

  • JavaScriptにおけるデータ型の概要
  • 代表的な型確認の方法であるtypeofinstanceofなどの使い分け
  • 配列やnull、オブジェクトの判定でよくあるハマりどころ
  • 実務での具体的な利用シーンと注意点
  • これらの方法を使って、安全にプログラムを実装するための考え方

JavaScriptで扱うデータ型の基本

JavaScriptでは、いくつかのデータ型が存在します。
大きく分けると、プリミティブ型オブジェクト型に分類されます。
まずは全体像をつかむため、どのような型があるのかを整理してみましょう。

プリミティブ型とは

プリミティブ型とは、ひとつの値を直接保持するシンプルな型です。
JavaScriptでは、次のような型がプリミティブ型に該当します。

  • number:整数も小数も区別なく扱います。
  • string:テキストを扱います。
  • boolean:true または false の真偽値を扱います。
  • undefined:値が割り当てられていない状態を意味します。
  • null:意図的に「何もない」値を示すために使用されます。
  • symbol:衝突しない一意の識別子を作るために使われる特殊な型です。
  • bigint:非常に大きな整数を扱うための型です。

プリミティブ型の値はイミュータブル(再代入不可な性質をもつ)であることが多いので、参照型との扱い方を混同しないように注意してください。

オブジェクト型

オブジェクト型は、複数のプロパティ(キーと値の組み合わせ)を持つ複雑なデータ構造を表します。
配列や関数、そしてそれぞれのインスタンスなども、すべてオブジェクト型に分類されるので、JavaScriptではオブジェクト型がかなり幅広い役割を担っていると考えるとよいでしょう。

undefined と null の扱い

初心者の皆さんが混乱しやすいのが、undefinednull です。
どちらも「中身がない」状態を表すものですが、その理由が異なります。

  • undefined:変数を宣言したが値が割り当てられていない状態
  • null:開発者の意思で「ここには値がない」という状態

この違いを理解しておくと、予期しないエラーや不具合を減らすことにつながります。
たとえば、後述するtypeof演算子で判定を行ったときに、返される文字列が異なるので注意してください。

typeof 演算子

JavaScriptで型を確認するときに、まず最初に多くの方が使用するのがtypeof演算子です。
変数の前に typeof をつけるだけで、その変数のデータ型を簡単にチェックできます。
最もシンプルな型判定の方法といえるでしょう。

typeof の基本

たとえば、次のように書くと文字列が返ってきます。

console.log(typeof 42);          // "number"
console.log(typeof "Hello");     // "string"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof null);        // "object"
console.log(typeof {});          // "object"
console.log(typeof Symbol());    // "symbol"
console.log(typeof 123n);        // "bigint"

typeof null"object" を返すのは、JavaScriptの設計上の仕様です。
初心者の方にとっては少し戸惑うかもしれませんが、これが意図された動作になっています。

typeof で発生しがちな落とし穴

先ほどの例で示したように、typeof null"object" と判定される点は特に有名な落とし穴です。
実務でも、nullを判定しようとして typeof を使い、その結果 "object" が返ってきて混乱するケースがしばしば見られます。
また、配列は実際にはオブジェクトの一種なので、typeof [] としても "object" が返ります。
そのため、typeof だけで配列を判定するのは難しいということを覚えておきましょう。

実務のシーンでは、簡単な「数値かどうか」「文字列かどうか」を判定するときにtypeofはよく使われます。
しかし、もう少し複雑な判定が必要な場合には、後述する方法と組み合わせるのが効果的です。

instanceof 演算子

JavaScriptで型を確認するもうひとつの手段として、instanceof 演算子があります。
これは「あるオブジェクトが特定のコンストラクタ関数から生成されたオブジェクトかどうか」をチェックするものです。

instanceof の基本

たとえば、配列はArrayコンストラクタから生成されるオブジェクトなので、次のように判定することができます。

console.log([] instanceof Array);     // true
console.log({} instanceof Object);    // true
console.log(new Date() instanceof Date); // true

JavaScriptではクラスベースのオブジェクト指向というより、プロトタイプベースの考え方を採用しているため、他の言語と同じ感覚でinstanceofを使うと戸惑うかもしれません。
しかし、実際の開発では配列判定やユーザー定義クラスのインスタンス判定で使われることが多く、覚えておくと便利です。

カスタムオブジェクトの判定

自分で作成したコンストラクタ関数(あるいはクラス構文で定義したクラス)がある場合、instanceof を使って「そのオブジェクトは自分の想定するクラスから生成されたものか」を確認できます。

class MyClass {}
const myInstance = new MyClass();

console.log(myInstance instanceof MyClass); // true

ただし、オブジェクトのプロトタイプチェーンを直接操作したり、Object.create() でコンストラクタを経由せずに生成したりすると、instanceof の結果が期待通りでないケースも出てきます。
また、異なるウィンドウやiframe間でオブジェクトをやり取りする場合は、instanceof判定が変わることがあるため注意しましょう。

Object.prototype.toString.call の利用

配列や日付などを厳密に判定したいとき、しばしば使われるのが Object.prototype.toString.call です。
Object.prototype.toString.call(変数) を実行すると、[object ~~~] という文字列が返されるので、その部分をチェックする方法が知られています。

メリット・デメリット

typeof ではオブジェクトとしか判定されない配列やnullでも、Object.prototype.toString.call であればより細かく区別ができます。
たとえば、次のような結果が得られます。

console.log(Object.prototype.toString.call([]));        // "[object Array]"
console.log(Object.prototype.toString.call({}));        // "[object Object]"
console.log(Object.prototype.toString.call(null));      // "[object Null]"
console.log(Object.prototype.toString.call(new Date())); // "[object Date]"

配列やnullを一発で区別したいときには便利ですが、このメソッドコールは少し冗長な印象を与えるかもしれませんね。
実務では、ライブラリの内部実装で使われることも多く、「もっと細かい型判定が必要だ」という局面に対応できる頼もしい方法といえます。

主な活用パターン

利用する際は、返ってきた文字列をさらに分解して、特定のキーワード("[object Array]" など)を含むかどうかで判定することが一般的です。

function getType(value) {
  return Object.prototype.toString.call(value).slice(8, -1);
}

console.log(getType([]));        // "Array"
console.log(getType({}));        // "Object"
console.log(getType(null));      // "Null"
console.log(getType(123));       // "Number"
console.log(getType("Hello"));   // "String"
console.log(getType(new Date())); // "Date"

こうしたユーティリティ関数を作っておくと、実務のいろいろな場面で再利用しやすいでしょう。
ただし、単に「数値かどうか」「配列かどうか」といった基本的な判定だけなら、よりシンプルな方法も存在するので、そちらを使うことが多いかもしれません。

Array.isArray の活用

配列の判定については、Array.isArray メソッドを使うことが推奨されています。
これは、配列であるかどうかを真偽値で返してくれる、非常にシンプルでわかりやすい組み込みのメソッドです。

console.log(Array.isArray([]));         // true
console.log(Array.isArray({}));         // false
console.log(Array.isArray("Hello"));    // false
console.log(Array.isArray(new Date())); // false

typeof で判定すると、すべて "object" が返ってしまう配列ですが、Array.isArray なら一発で解決します。
実務では、多くの場合これだけで配列かどうかの判定を行うことが十分でしょう。

配列判定には Array.isArray を使う、というのはモダンなJavaScriptの基本スタイルです。

null の判定方法

先ほども触れましたが、typeof null"object" を返す仕様があるため、typeof だけではnullを厳密に判定できません。
そのため、一般的には value === null のように、直接比較を行う形がよく使われます。

const value = null;

if (value === null) {
  console.log("これはnullです");
} else {
  console.log("nullではありません");
}

このように、明示的に比較するのが最もシンプルで誤解がありません。
「オブジェクト型かどうか」だけでは区別が難しい場合があるので、nullを扱うときには=== nullという直接チェックを頭に入れておくといいでしょう。

NaN の判定

もうひとつ特殊な値として、数値型なのに「Not a Number」を意味する NaN があります。
NaNの判定には、isNaNNumber.isNaN を使う方法があります。
ただし、isNaN は引数を数値に変換しようとする挙動があり、文字列などを誤ってNaNと判定してしまう可能性があります。
一方、Number.isNaN は「その値がNaNかどうか」を厳密に判定する仕組みになっているので、現在では Number.isNaN の利用が推奨されることが多いです。

console.log(isNaN("Hello"));          // true  (暗黙の型変換でNaN扱い)
console.log(Number.isNaN("Hello"));   // false (厳密なチェック)
console.log(Number.isNaN(NaN));       // true
console.log(Number.isNaN(123));       // false

実務でも、数値計算でエラーが出ないようにNaN判定を入れるシーンがあるので、誤った方法で判定してしまうと不具合の原因になります。
NaNは「自分自身との比較ができない」という性質があり、NaN === NaNfalse になるという特殊な仕様もあるため、注意が必要です。

型の変換と暗黙的キャスト

JavaScriptは動的型付け言語なので、暗黙のうちに型変換が行われることがよくあります。
たとえば、数値と文字列が混ざると自動的に文字列として扱われたり、== を使うときには予期しない型変換が生じることがあります。
こうした挙動を理解していないと、型のチェックを行っているはずなのに意図しない動きをするケースがあるかもしれません。

厳密等価演算子(===)を使う理由

暗黙の型変換を避けたい場合は、===(厳密等価演算子) を利用して比較するのが基本です。
== だと文字列と数値の比較や、true1 のような比較でも暗黙の型変換が起きてしまいます。
たとえば、1 == "1"true ですが、1 === "1"false になります。
型の確認が絡む処理では、できるだけ === を使うのがセオリーです。

実務での活用シーンと注意点

ここでは、型確認を行う具体的なシーンをいくつか挙げます。
初学者の方が開発現場に入ったとき、実際にどのように使われるかイメージをつかんでみてください。

フォーム入力値の検証

Webアプリでは、フォームから送信されてきた値が数値か文字列かを判定するシーンがよくあります。
typeof や正規表現を組み合わせたり、必要に応じてNumber.isNaNで厳密に数値チェックをすることも多いです。
ここで型を取り違えると、データベースに保存するときに不備が出たり、エラーにつながったりします。

APIレスポンスの判定

外部APIから返ってくるデータが期待通りの型かどうかをチェックするのは、バグを未然に防ぐうえでとても大切です。
たとえば、配列が返ってくると思っていたら実際にはオブジェクトだった場合、処理を進める前に Array.isArray などで判定するようにしておくと安全です。

ユーティリティ関数の作成

前述の Object.prototype.toString.call を活用したgetType関数のように、プロジェクト内でよく使う型判定ロジックをひとまとめにしておくケースもあります。
こうすると、各所で同じコードを繰り返し書かずに済むだけでなく、可読性や保守性の向上にもつながります。

開発チーム全体で、どのように型判定を行うかの方針を決めておくと、コードの整合性が保ちやすくなります。

クライアントとサーバーのやり取り

JavaScriptはクライアントサイド(ブラウザ)でもサーバーサイド(Node.js)でも同じ言語を使えるため、データの型を一致させることが重要です。
API設計時に「ここでは文字列を返す」「ここでは配列を返す」と明示しておき、受け取った側でも同じ型を期待しているかどうかを確認する仕組みを入れておくと、やり取りがスムーズに進みます。

例外的なケースと高度な利用法

ここまで紹介した方法以外にも、TypeScriptなどの型定義を導入することで、コード全体の型チェックを高度に行う手段も存在します。
ただし、JavaScriptだけで完結させる場合は、今回紹介したtypeofinstanceofObject.prototype.toString.callArray.isArray などを使い分ければ、ほとんどの基本的な型判定ニーズに対応できます。

関数やクラスの判定

  • 関数typeof functionName === "function" でチェック
  • クラス:実際にはクラスもコンストラクタ関数の糖衣構文として実装されているため、instanceof が活用される

ランタイム環境の違い

ブラウザかNode.jsか、さらには古いバージョンのJSランタイムかなどによって、使えるメソッドの差があることも稀にあります。
しかし、現在では多くのモダン環境でArray.isArrayNumber.isNaNがサポートされています。
どうしても古い環境をサポートしなければならない場合には、ポリフィルを検討することがあります。

JavaScriptで型を正しく扱うためのポイント

これまで紹介してきた内容を踏まえて、型確認で気をつけるべきポイントをまとめてみます。
初心者の皆さんがつまずきやすいポイントと、その対策を意識してみてください。

1. null と配列は typeof だけでは区別できない

typeof nulltypeof [] はどちらも "object" となるため、単にtypeofで判定するのは不十分です。
この場合はArray.isArrayvalue === null を使ったほうがいいでしょう。

2. NaN は自分自身と等価にならない

NaN === NaNfalse なので、Number.isNaN を利用して厳密にチェックするのが良いです。

3. クラスや配列、日付などの判定には instanceof が便利

ただし、異なるコンテキスト(iframeや別ウィンドウ)で生成されたオブジェクトには注意が必要。
プロトタイプチェーンが異なると、instanceof の結果が意外なものになることがあります。

4. 詳細な判定には Object.prototype.toString.call

もっと細かい型情報が必要なときには便利です。
ただし、毎回それを使うとコードが煩雑になるため、用途に応じて使い分けをするようにしましょう。

5. 暗黙の型変換を意識する

== を使わずに === を使う、文字列と数値が混在した比較に気をつける、といった対策が必要です。
暗黙の型変換が起こる場面を知っておくだけでも、バグを減らすことにつながります。

まとめ

JavaScriptは動的型付け言語なので、型の取り扱いには柔軟性がある一方、予期せぬバグを生み出してしまうことがあります。
しかし、この記事で紹介したtypeof, instanceof, Object.prototype.toString.call, Array.isArray, Number.isNaN などをしっかりと使いこなせるようになれば、大抵の場面で正しく型を判定することができるでしょう。

実務ではフォームの入力チェックやAPIのレスポンス確認、オブジェクトの種類を見分けるなど、型確認が欠かせないシーンが多々あります。
それぞれの判定方法の特徴や得意・不得意を把握して、適切な手段を選んでみてください。
型を明確にすることで、開発の安定性と可読性を高めることができるはずです。

JavaScriptをマスターしよう

この記事で学んだJavaScriptの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。