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

JavaScript JavaScript
スポンサーリンク

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

正の数判定は、「その値が“0 より大きい数値として扱ってよいか”どうか」を見分けることです。
業務では「数量」「個数」「ページ番号」「在庫数」「ポイント」「金額(マイナス不可)」など、「正の数だけ許可したい」場面がとても多くあります。

もしここを曖昧にしてしまうと、「-1 個の在庫」「0 ページ目」「マイナス金額」といった、ありえない値がシステムに入り込みます。
なので、「数値かどうか」と「正の数かどうか」をきちんと分けて判定するユーティリティが、とても重要になります。


まずは「正の数」をきちんと定義する

正の数判定を実装する前に、「自分のプロジェクトでは何を“正の数”とみなすか」をはっきりさせる必要があります。
数学的には「0 より大きい数」を正の数と呼びますが、業務では次のような微妙な違いがよく出てきます。

0 は許可するのか(0 以上か、0 より大きいだけか)。
小数は許可するのか(1.5 個を許すのか、整数だけか)。

ここではまず、「0 より大きい数値(小数も含む)」を正の数とし、そのあとで「整数だけに絞る」パターンも触れます。


型が number の場合のシンプルな正の数判定

まずは「すでに number 型である」ことが分かっている場合の、いちばん素直な実装です。

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

console.log(isPositiveNumber(1));     // true
console.log(isPositiveNumber(0.5));   // true
console.log(isPositiveNumber(0));     // false
console.log(isPositiveNumber(-1));    // false
console.log(isPositiveNumber(NaN));   // false
console.log(isPositiveNumber("1"));   // false
JavaScript

ここで重要なポイントは三つあります。

一つ目は、「型が number かどうか」を必ずチェックしていることです。
文字列 "1" は見た目は数値っぽいですが、この関数では false にしています。「number 型専用」と割り切っているからです。

二つ目は、「NaN を除外している」ことです。
typeof NaN === "number" なので、そのままだと NaN も「正の数」と誤判定されてしまいます。!Number.isNaN(value) を入れることで、「壊れた数値」を弾いています。

三つ目は、「0 を含めるかどうかを明示的に決めている」ことです。
ここでは value > 0 としているので、「0 は正の数ではない」という扱いになっています。もし「0 以上」を許可したいなら、value >= 0 に変えれば OK です。


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

実務では、「フォーム入力」「API レスポンス」など、数値が文字列で渡ってくることが多いです。
そこで、「number でも string でも受け付けて、正の数として扱えるかどうかを判定する」ユーティリティを作ってみます。

function isPositiveNumeric(value) {
  if (typeof value === "number") {
    return !Number.isNaN(value) && value > 0;
  }

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

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

  return false;
}

console.log(isPositiveNumeric(1));        // true
console.log(isPositiveNumeric("1"));      // true
console.log(isPositiveNumeric(" 1.5 "));  // true
console.log(isPositiveNumeric(0));        // false
console.log(isPositiveNumeric("0"));      // false
console.log(isPositiveNumeric("-1"));     // false
console.log(isPositiveNumeric("abc"));    // false
console.log(isPositiveNumeric(""));       // false
console.log(isPositiveNumeric(null));     // false
JavaScript

ここで深掘りしたいポイントは次の通りです。

number の場合は、さきほどの isPositiveNumber と同じロジックで判定しています。
string の場合は、まず空文字や空白だけを弾き、そのうえで Number(value) で数値に変換し、NaN かどうかと 0 より大きいかどうかをチェックしています。
それ以外の型(null, undefined, オブジェクトなど)はすべて false にしています。「数値として扱えるのは number と string だけ」というルールを明示しています。

この isPositiveNumeric を「入力値のバリデーション」に使うと、「正の数として扱ってよいか」を一発で判定できるようになります。


「正の整数だけ」を許可したい場合

数量や個数など、「小数はダメで、1, 2, 3 のような正の整数だけ許可したい」場面も多いです。
その場合は、「整数かどうか」のチェックを追加します。

function isPositiveInteger(value) {
  if (typeof value === "number") {
    return Number.isInteger(value) && value > 0;
  }

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

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

  return false;
}

console.log(isPositiveInteger(1));      // true
console.log(isPositiveInteger("1"));    // true
console.log(isPositiveInteger(1.5));    // false
console.log(isPositiveInteger("1.5"));  // false
console.log(isPositiveInteger(0));      // false
console.log(isPositiveInteger(-1));     // false
JavaScript

ここでは Number.isInteger を使って、「整数かどうか」を判定しています。
「正の数」と「正の整数」は業務上の意味が違うので、ユーティリティも分けておくと読みやすくなります。


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

正の数判定は、「数値として妥当か」「0 より大きいか」を見ているだけです。
実務では、ここにさらに「上限」「下限」「桁数」などの業務ルールが乗ってきます。

例えば、「数量は 1〜100 の範囲だけ許可したい」という要件なら、次のように書きます。

function isValidQuantity(value) {
  if (!isPositiveInteger(value)) return false;

  const n = Number(value);
  return n >= 1 && n <= 100;
}

console.log(isValidQuantity("3"));   // true
console.log(isValidQuantity("0"));   // false
console.log(isValidQuantity("101")); // false
console.log(isValidQuantity("abc")); // false
JavaScript

ここでのポイントは、「正の整数かどうか」と「業務上の範囲チェック」を分けていることです。
isPositiveInteger はあくまで「型+正の整数」の判定だけを担当し、
「1〜100 だけ許可」という業務ルールは isValidQuantity の中に閉じ込めています。

こうしておくと、「別の画面では 1〜1000 を許可したい」といった要件が出ても、
isPositiveInteger はそのまま使い回せます。


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

フォーム入力の例を考えてみます。
ユーザーが「数量」として文字列を入力し、それをサーバーに送る前にチェックしたいとします。

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

if (!isPositiveInteger(raw.quantity)) {
  console.log("数量は 1 以上の整数で入力してください");
} else {
  const quantity = Number(raw.quantity);
  console.log("数量:", quantity);
}
JavaScript

ここでは、「文字列かもしれない」「空文字かもしれない」「小数かもしれない」「マイナスかもしれない」といった可能性を、
isPositiveInteger 一発でふるいにかけています。

同じように、「金額は 0 以上の数値(小数も可)」という要件なら、isPositiveNumeric を少し変えて >= 0 にするだけで対応できます。


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

自分で isPositiveNumber, isPositiveNumeric, isPositiveInteger を実装して、次の値を片っ端から試してみてください。

1, 0, -1, 1.5, "1", "0", "-1", "1.5", "abc", "", " ", NaN, null, undefined

それぞれに対して、「どの関数が true になるか」「どこで false になるか」をコンソールに出してみると、
「数値判定」「NaN 判定」「正の数判定」「正の整数判定」が頭の中でちゃんと分かれてきます。

ここまで整理できれば、あとは自分の業務ルールに合わせて「0 を含めるか」「小数を許すか」「上限をどうするか」を足していくだけです。

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