JavaScript Tips | 基本・共通ユーティリティ:型チェック – 数値判定

JavaScript JavaScript
スポンサーリンク

「数値判定」とは何を見分けたいのか

ここでいう「数値判定」は、その値が「本当に“数値として扱っていいものか”どうか」を見分けることです。
JavaScript では、"10" のような文字列も、10 のような number も、"10px" のような文字列も、全部「それっぽく」見えてしまいます。

業務コードでは、次のようなことをよくやります。

const total = price * quantity;
JavaScript

ここで pricequantity が「数値ではない」のにそのまま計算すると、NaN(Not a Number)が発生して、
そのままどこかに流れていき、原因が分かりづらいバグになります。

だからこそ、「これは数値として扱っていいか?」を事前にチェックする「数値判定ユーティリティ」が重要になります。


JavaScript の「数値っぽいもの」を整理する

まず、「数値まわりのよくあるパターン」をざっくり整理しておきます。

const a = 10;          // number 型(数値)
const b = "10";        // 文字列だが、数値に変換できそう
const c = "10px";      // 数値+単位
const d = "abc";       // 数値に変換できない
const e = NaN;         // number 型だが「数値としては壊れている」
JavaScript

ここで大事なのは、「NaNtypeof では number になる」という点です。

console.log(typeof 10);   // "number"
console.log(typeof NaN);  // "number"
JavaScript

つまり、「typeof value === 'number' だけでは“まともな数値かどうか”は分からない」ということです。


「型として number かどうか」と「有効な数値かどうか」を分ける

数値判定を考えるときは、次の二段階に分けると整理しやすくなります。

  1. 型として number かどうか
  2. その numberNaN ではないかどうか

型として number かどうか

まずは素直に typeof を使います。

function isNumberType(value) {
  return typeof value === "number";
}

console.log(isNumberType(10));     // true
console.log(isNumberType("10"));   // false
console.log(isNumberType(NaN));    // true(ここがポイント)
console.log(isNumberType(null));   // false
JavaScript

「型として number かどうか」を知るだけなら、これで十分です。
ただし、NaN も true になってしまうので、「有効な数値かどうか」を知りたいときはもう一歩踏み込む必要があります。

有効な数値かどうか(NaN を除外する)

NaN かどうかを判定するには、Number.isNaN を使います。

console.log(Number.isNaN(NaN));          // true
console.log(Number.isNaN(10));           // false
console.log(Number.isNaN("abc"));        // false
console.log(Number.isNaN(Number("abc"))); // true
JavaScript

これを組み合わせて、「型が number で、かつ NaN ではない」=「有効な数値」と判定できます。

function isValidNumber(value) {
  return typeof value === "number" && !Number.isNaN(value);
}

console.log(isValidNumber(10));   // true
console.log(isValidNumber(NaN));  // false
console.log(isValidNumber("10")); // false
JavaScript

業務で「計算に使っていい数値か?」を判定したいときは、この isValidNumber レベルのチェックが欲しくなります。


文字列を「数値として見ていいか」を判定したい場合

実務では、「最初から number 型で来る」ことの方が少なくて、
フォーム入力や API レスポンスなど、「文字列として来る」ケースが多いです。

例えば、"10", "10.5", "0", "abc" などです。
これらを「数値として扱っていいか?」を判定したいときは、いったん Number で変換してから考えます。

function isNumericString(value) {
  if (typeof value !== "string") return false;
  if (value.trim() === "") return false; // 空文字は数値とみなさない

  const n = Number(value);
  return !Number.isNaN(n);
}

console.log(isNumericString("10"));      // true
console.log(isNumericString("10.5"));    // true
console.log(isNumericString("  20  "));  // true
console.log(isNumericString(""));        // false
console.log(isNumericString("   "));     // false
console.log(isNumericString("abc"));     // false
console.log(isNumericString("10px"));    // false
JavaScript

ここで深掘りしたいポイントは三つあります。

一つ目は、「文字列以外は即 false」にしていることです。
isNumericString は「文字列が数値として妥当か」を見る関数なので、役割をはっきりさせています。

二つ目は、「空文字や空白だけの文字列は数値とみなさない」と決めていることです。
Number("") は 0 になりますが、業務的には「未入力」として扱いたいことが多いので、ここで弾いています。

三つ目は、「Number で変換してから NaN かどうかを見る」という流れです。
Number("10px") は NaN になるので、「途中に文字が混ざっているもの」は数値として不適切だと判定できます。


「数値として扱えるか」を総合的に判定するユーティリティ

ここまでの考え方をまとめて、「いろいろな値が来ても“数値として扱えるか”を判定する」関数を作ってみます。

function isNumeric(value) {
  if (typeof value === "number") {
    return !Number.isNaN(value);
  }

  if (typeof value === "string") {
    if (value.trim() === "") return false;
    const n = Number(value);
    return !Number.isNaN(n);
  }

  return false;
}

console.log(isNumeric(10));        // true
console.log(isNumeric(NaN));       // false
console.log(isNumeric("10"));      // true
console.log(isNumeric("10.5"));    // true
console.log(isNumeric(""));        // false
console.log(isNumeric("abc"));     // false
console.log(isNumeric("10px"));    // false
console.log(isNumeric(null));      // false
console.log(isNumeric(undefined)); // false
JavaScript

この isNumeric は、「number 型の有効な数値」か「数値に変換可能な文字列」だけを true にします。
業務で「この値を数値として扱ってよいか?」をざっくり判定したいときに、とても使いやすい形です。


数値判定と「バリデーション」「変換」をどう分けるか

実務でよくある失敗が、「数値判定」「変換」「業務ルールのチェック」をごちゃ混ぜにしてしまうことです。

例えば、こんなコードです。

const n = Number(input);

if (!n) {
  console.log("不正な値");
}
JavaScript

このコードは、0NaN""null などを全部「不正」とみなしてしまいます。
「0 は有効な値なのに弾かれてしまう」という典型的なバグです。

よりよい考え方は、段階を分けることです。

  1. 「数値として解釈できるか?」(数値判定+変換)
  2. 「業務ルールとして妥当か?」(範囲チェックなど)
const n = isNumeric(input) ? Number(input) : null;

if (n === null) {
  console.log("数値として解釈できません");
} else if (n < 0) {
  console.log("0 以上を入力してください");
} else {
  console.log("OK:", n);
}
JavaScript

このように、「数値として扱えるか」と「業務的に許可するか」を分けて書くと、
コードの意図がはっきりし、バグの原因も追いやすくなります。


実務での具体的な利用イメージ

フォーム入力のチェック

数量や金額などをフォームで入力させるケースを考えます。

const raw = {
  quantity: "3",
  unitPrice: "1200",
};

if (!isNumeric(raw.quantity)) {
  console.log("数量が数値ではありません");
} else if (!isNumeric(raw.unitPrice)) {
  console.log("単価が数値ではありません");
} else {
  const quantity = Number(raw.quantity);
  const unitPrice = Number(raw.unitPrice);
  const total = quantity * unitPrice;
  console.log("合計金額:", total);
}
JavaScript

ここでは、「数値として扱えるか?」を isNumeric で判定し、
そのあとで Number で変換して計算しています。

CSV や外部データの取り込み

CSV や外部システムからのデータは、基本的に全部文字列です。
その中から「数値として扱えるものだけを抽出したい」ときにも、数値判定ユーティリティが役立ちます。

const rows = ["10", "20", "abc", "30"];

const numbers = rows
  .filter(isNumeric)
  .map((v) => Number(v));

console.log(numbers); // [10, 20, 30]
JavaScript

このように、「判定」と「変換」を組み合わせることで、
「壊れたデータを静かに混ぜてしまう」リスクを減らせます。


小さな練習で感覚をつかむ

最後に、手を動かして慣れるためのミニ課題を提案します。

自分で isNumberType, isValidNumber, isNumericString, isNumeric を実装して、次の値を片っ端から試してみてください。

10, 0, -1, NaN, "10", "10.5", " 20 ", "abc", "10px", "", " ", null, undefined

それぞれに対して、「どの関数が true を返すか」「どこで false になるか」をコンソールに出してみると、
「型としての number」と「有効な数値」と「数値に変換可能な文字列」が、頭の中でちゃんと分かれてきます。

そこまで行けたら、もう数値判定は実務レベルです。
あとは、自分のプロジェクトの要件に合わせて、「どこまでを許容するか」を微調整していけば OK です。

タイトルとURLをコピーしました