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

JavaScript JavaScript
スポンサーリンク

有限数判定とは何を見分けたいのか

有限数判定は、「その値が 無限大(Infinity / -Infinity)でもなく、NaN でもなく、ちゃんとした“有限の数値”かどうか」を見分けることです。

業務では、次のような値が紛れ込むことがあります。

  • 計算の結果 Infinity になってしまう
  • 0 で割って Infinity が発生する
  • 数値変換に失敗して NaN が生まれる
  • API から "Infinity" のような文字列が返ってくる
  • 入力値が "abc" のような文字列で、変換すると NaN になる

こうした「壊れた数値」や「無限大」をそのまま計算に使うと、
結果がすべて壊れる(NaN 伝染)
画面に “Infinity” が表示されてしまう
などの事故が起きます。

だからこそ、「有限の数値かどうか」を判定するユーティリティは、実務で非常に重要です。


JavaScript の数値まわりの落とし穴を整理する

JavaScript の number 型には、次のような特殊値があります。

Infinity
-Infinity
NaN

そして、これらはすべて typeof value === "number" で true になります。

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

つまり、「型が number だから安全」とは限らないのです。


有限数判定の正解:Number.isFinite

有限数かどうかを判定する最も正しい方法は、Number.isFinite を使うことです。

console.log(Number.isFinite(10));        // true
console.log(Number.isFinite(-5.5));      // true
console.log(Number.isFinite(Infinity));  // false
console.log(Number.isFinite(-Infinity)); // false
console.log(Number.isFinite(NaN));       // false
console.log(Number.isFinite("10"));      // false(ここが重要)
JavaScript

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

1. Infinity / -Infinity を除外できる

Number.isFinite は、無限大を自動的に false にします。

2. NaN を除外できる

Number.isFinite(NaN) は false です。
「壊れた数値」を確実に弾けます。

3. 文字列は自動変換しない

Number.isFinite("10") は false です。
「文字列を勝手に数値とみなさない」という安全な挙動になっています。


グローバル isFinite との違い

JavaScript には、歴史的に isFinite というグローバル関数もあります。

console.log(isFinite("10")); // true(ここが危険)
console.log(isFinite("abc")); // false
JavaScript

グローバル isFinite は、文字列を数値に変換してから判定するため、
"10" のような文字列も true になってしまいます。

実務ではこの挙動がバグの原因になるため、
有限数判定は必ず Number.isFinite を使う
と覚えてしまうのが安全です。


number 型専用の有限数判定ユーティリティ

まずは、number 型だけを対象にしたシンプルな関数です。

function isFiniteNumber(value) {
  return typeof value === "number" && Number.isFinite(value);
}

console.log(isFiniteNumber(10));        // true
console.log(isFiniteNumber(-3.14));     // true
console.log(isFiniteNumber(Infinity));  // false
console.log(isFiniteNumber(NaN));       // false
console.log(isFiniteNumber("10"));      // false
JavaScript

この関数は、「型が number で、かつ有限数」であることを保証します。


文字列も受け付ける「実務向けの有限数判定」

フォーム入力や API レスポンスでは、数値が文字列で来ることが多いので、
「number でも string でも受け付ける」関数を作っておくと便利です。

function isFiniteNumeric(value) {
  if (typeof value === "number") {
    return Number.isFinite(value);
  }

  if (typeof value === "string") {
    if (value.trim() === "") return false;

    const n = Number(value);
    return Number.isFinite(n);
  }

  return false;
}

console.log(isFiniteNumeric("10"));      // true
console.log(isFiniteNumeric("10.5"));    // true
console.log(isFiniteNumeric("abc"));     // false
console.log(isFiniteNumeric(""));        // false
console.log(isFiniteNumeric("Infinity")); // false
console.log(isFiniteNumeric(Infinity));   // false
JavaScript

ここでのポイントは、

  • 空文字は false
  • 数値変換に失敗したら false
  • Infinity / -Infinity も false

という「実務で安全な判定」をしていることです。


有限数判定と「業務ルール」の分け方

有限数判定は、「壊れていない数値かどうか」を見るだけです。
実務では、ここにさらに「範囲」「桁数」「正負」などの業務ルールが乗ってきます。

例えば、「金額は 0 以上の有限数だけ許可したい」という要件ならこうなります。

function isValidAmount(value) {
  if (!isFiniteNumeric(value)) return false;

  const n = Number(value);
  return n >= 0;
}

console.log(isValidAmount("100"));  // true
console.log(isValidAmount("-1"));   // false
console.log(isValidAmount("abc"));  // false
console.log(isValidAmount("Infinity")); // false
JavaScript

有限数判定をベースにして、業務ルールを積み上げるイメージです。


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

API からの数値レスポンスを検証する

API が壊れて Infinity を返してくることは、実際によくあります。

async function fetchRate() {
  const res = await fetch("/api/rate");
  const data = await res.json();

  if (!isFiniteNumeric(data.rate)) {
    throw new Error("API から不正なレートが返ってきました");
  }

  return Number(data.rate);
}
JavaScript

ここで有限数判定を挟んでおくことで、
「Infinity が混ざって計算が壊れる」事故を防げます。

計算結果の安全性チェック

計算の途中で Infinity が発生していないかを確認するのも重要です。

function safeDivide(a, b) {
  const result = a / b;

  if (!Number.isFinite(result)) {
    throw new Error("計算結果が有限数ではありません");
  }

  return result;
}

console.log(safeDivide(10, 2)); // 5
console.log(safeDivide(10, 0)); // ここで例外(Infinity)
JavaScript

「0 で割ってしまった」などのミスを早期に検知できます。


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

次の値を Number.isFiniteisFiniteNumeric に渡して、結果を比べてみてください。

10, -5, 0, 1.5, Infinity, -Infinity, NaN, "10", "10.5", "abc", "Infinity", "", " "

どの値が true になり、どれが false になるかを確認すると、
「有限数」「無限大」「NaN」「数値に変換可能な文字列」の違いがはっきり理解できます。

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