順番に読み進めながら学べます

データ型まとめ — typeof と判定の早見表

ここまでに出てきた値を型の観点で整理します。7 つのプリミティブと Object の分類、typeof の戻り値、null と配列が object になる理由、数値として扱えるかの判定までまとめます。

JavaScript で扱う値は、文字列・数値・真偽値・配列・オブジェクト・nullundefined・Map・Set と多岐にわたります。実務では、フォームやサーバーから届いた値が期待した型かどうかを確かめてから処理を進めます。

この記事では、それらを型という 1 つの観点で整理し、typeof の結果と、型ごとの正しい確かめ方をまとめます。

型は 7 つのプリミティブと Object に分かれる

型が分かると、その値に対して何ができるかが決まります。文字列なら lengthslice が使え、数値なら計算ができ、配列なら push が使えます。

逆に、届いた値の型を取り違えたまま処理を進めると、undefinedNaN が紛れ込んだことに気づかないまま、処理が最後まで進んでしまいます。

JavaScript の値は、プリミティブ(数値・文字列・真偽値・nullundefinedsymbolbigint の 7 つ。オブジェクトや配列ではない値)と Object(プロパティを持つ値。配列・Map・Set もここに含まれる)に分かれます。

この講座で扱ってきたのは、プリミティブのうち前の 5 つと Object です。

残る 2 つのうち symbol(重複しない一意のキーを作るための値)は特殊なキーを作る場面で、bigint(非常に大きな整数を専用に扱うための値)は Number では正確に表せない桁の整数を扱う場面で使います。どちらもこの講座の範囲では登場しないので、名前と位置づけだけ押さえておけば十分です。

値の分類
string文字列number数値boolean真偽値null空を示すundefined値が無いsymbol と bigintこの講座では扱わないオブジェクト配列Map と Setプリミティブ 7 つObject の仲間
上の 2 行が プリミティブ(この講座で扱う 5 つ + 扱わない 2 つ)、下の行が Object の仲間 です。配列も Map も Set も Object に含まれます。

型を調べる演算子が typeof です。値の前に書くと、型の名前を文字列で返します。

返る文字列は決まっていて、"string" "number" "boolean" "undefined" "symbol" "bigint" "object" "function" の 8 種類です。"function" は関数を渡したときだけ返る結果で、関数は次のカテゴリで扱います。

値の例分類typeof の結果
ORD-6033 のような文字列プリミティブstring
9800 のような数値プリミティブnumber
true と falseプリミティブboolean
値を入れていない変数プリミティブundefined
nullプリミティブobject
オブジェクトと配列Objectobject
console.log(typeof "ORD-6033");             // string
console.log(typeof 9800);                   // number
console.log(typeof true);                   // boolean
console.log(typeof undefined);              // undefined

console.log(typeof { orderId: "ORD-6033" });  // object
console.log(typeof [1, 2]);                   // object

// null もプリミティブだが typeof は object を返す
console.log(typeof null);                   // object

いろいろな型が混ざった 4 つの値に typeof を掛けて、返る文字列を確かめます。values は宣言済みです。

① 4 つの値の型を 1 行ずつ表示してください。

② 4 つの型を「, 」でつないで 1 行で表示してください。

③ ② で並べた型から重複を取り除いて、型の種類数を表示してください。

(正しく実行できれば解説が表示されます)

JavaScript / TypeScript エディタ

コードを実行してください

typeof が object を返す 3 つ — null と配列とオブジェクト

サーバーから届いた値が「配送先オブジェクト」なのか「まだ選ばれていない null」なのか「商品の配列」なのかで、次にする処理は変わります。ところが typeof はこの 3 つに同じ "object" を返すので、判定にそのまま使えません。

typeof null"object" を返すのは、JavaScript の最初期からある動作です。仕様上の誤りとして知られていますが、直すと既存のコードが壊れるためそのまま残っています。

null かどうかは value === null で直接調べます。

配列かどうかは Array.isArray(value) で調べます。配列を渡したときだけ true を返すので、オブジェクトや null と区別できます。

この 2 つを先に除けば、残った "object" が「配列でも null でもないオブジェクト」です。

object が返ったあとの見分け方
nulltypeof はobject=== null で判定する配列typeof はobjectArray.isArrayで判定するオブジェクトtypeof はobject上の 2 つを除いた残り
3 つとも typeofobject です。値ごとに別の書き方で見分けます。どちらでもなければオブジェクトです。
const shipping = null;
const cart = ["マウス"];
const order = { orderId: "ORD-6033" };

// typeof は 3 つとも同じ結果を返す
console.log(typeof shipping);      // object
console.log(typeof cart);          // object

// null は === で直接調べる
console.log(shipping === null);    // true

// 配列は Array.isArray で調べる
console.log(Array.isArray(cart));  // true
console.log(Array.isArray(order)); // false

// 配列でも null でもないオブジェクトかどうか
console.log(typeof order === "object" && order !== null && !Array.isArray(order));  // true

null を先に除いてから中身を読む

typeof value === "object" だけを条件にして中身を読むと、valuenull のときに TypeError で止まります。nulltypeof では素通りしてしまうので、value !== null を先に確かめるか、value?.city のようにオプショナルチェーンを挟みます。

API から届いた応答オブジェクトの各項目を、型で分類します。response は宣言済みです。

① 4 項目の型を「キー: 型」の形で 1 行ずつ表示してください。

② items と coupon が配列かどうかを「キー: 判定」の形で表示してください。

③ shipping が null かどうかを表示してください。

④ coupon が「配列でも null でもないオブジェクト」かどうかを、3 つの条件をつないだ式で表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

文字列を数値として扱えるか — Number と Number.isNaN

ここまでは typeof で型そのものを見分ける方法を扱いましたが、型がわかっても中身が期待どおりとは限りません。フォームから届く数量や金額は、見た目が数字でも型は文字列です。計算に使う前に「数値として扱えるか」を確かめないと、"12px" のような値がそのまま計算に流れて NaN を生みます。

ここでは型そのものではなく、変換できるかどうかを調べます。

Number(input) で変換し、結果が NaN かどうかを Number.isNaN(変換結果) で調べる方法は型変換の記事で扱いました。ここで型の判定と切り分けたいのは、これは型の確認ではなく中身の確認だという点です。

"9800""abc"typeof はどちらも "string" で、数量として使えるかどうかは型からは分かりません。

落とし穴は空文字列です。Number("")NaN ではなく 0 を返すため、未入力のフォームが「数量 0 の有効な入力」として通ってしまいます。

空文字列を弾きたいときは、変換の前に input !== "" を確かめます。

文字列を数値に変換したときの結果
"9800"Number で変換する9800扱える"12px"Number で変換するNaN扱えない空文字列Number で変換する0通ってしまう
数字だけの文字列は数値になり、数字以外が混ざると NaN です。空文字列だけは 0 になるので、変換前に弾きます
console.log(Number("9800"));               // 9800
console.log(Number("abc"));                // NaN
console.log(Number(""));                   // 0(NaN ではない)

// 変換した結果が NaN かどうかを調べる
console.log(Number.isNaN(Number("abc")));  // true
console.log(Number.isNaN(Number("9800"))); // false

// 空文字列は 0 として通ってしまう
console.log(Number.isNaN(Number("")));     // false

フォームから届いた 4 つの入力が、数量として使えるかどうかを判定します。inputs は宣言済みです。

① 4 つを数値に変換した結果を「, 」でつないで表示してください。

② 変換した結果が NaN でないかどうかを、入力とあわせて「入力: 判定」の形で 1 行ずつ表示してください。

③ 未入力を弾く条件を足すと、空文字列の判定がどう変わるかを、条件 1 つの場合と 2 つの場合で並べて表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

判定の使い分け — 早見表

型を確かめる書き方は 1 つではありません。typeof で足りる型と、typeof の結果からさらに絞り込む必要がある型があり、文字列の中身が数値かどうかは型とは別の確認です。調べたいことから書き方を選びます。

調べたいことから書き方を選ぶ
調べたい値typeof がobject 以外typeof の結果で決まる調べたい値typeof がobject=== null とArray.isArray数字に見える文字列型ではなく中身を見たいNumber とNumber.isNaN
typeof で決まるのは object 以外の型です。object が返ったときと、文字列の中身を見たいときは別の書き方に切り替えます
調べたいこと書き方注意
文字列・数値・真偽値かtypeof value === "string" などそのまま使える
値が入っていないかvalue === undefinedtypeof でも判定できる。既定値を当てたいだけなら ?? (第 9 回)
null かvalue === nulltypeof では object になる
配列かArray.isArray(value)typeof では object になる
ただのオブジェクトかtypeof が object かつ null と配列を除く3 つの条件を && でつなぐ
数値として扱えるかNumber に変換して Number.isNaN で確認空文字列は 0 になる
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1typeof null は何を返しますか?

Q2配列かどうかを確かめる書き方はどれですか?

Q3Number("") は何を返しますか?