- 業務・実務で使える JavaScript ユーティリティ:数値かどうか判定する方法
- 最初に整理する:「数値かどうか」には3種類ある
- ステップ1:まずはJavaScriptの数値型かどうか判定する
- ステップ2:有限の数値かどうかを判定する
- ステップ3:文字列として数値を受け取りたい場合を考える
- ステップ4:parseInt() や parseFloat() を判定用途に使いすぎない
- ステップ5:何を許可するかを業務ルールとして決める
- 業務で使える基本テンプレート その1:有限の数値型か判定する
- 業務で使える基本テンプレート その2:数値として読める文字列か判定する
- 業務で使える完成版テンプレート:数値判定と用途別ルールを分ける
- 注意が必要なケースを深掘りする
- 実務でよくある用途別の判定例
- テストで境界条件を確認する
- まとめ
業務・実務で使える JavaScript ユーティリティ:数値かどうか判定する方法
JavaScriptで「数値かどうか」を判定したい場面は非常に多いです。フォーム入力の金額、CSVから読み込んだ数量、APIで受け取った価格、ページ番号、在庫数、割引率など、業務システムでは数値の扱いが頻繁に登場します。
ただし、ここで最初に理解しておきたいのは、「数値かどうか」は1通りではないということです。たとえば、123 のようなJavaScriptの数値型だけを許可したいのか、"123" のような文字列も「数値として読める値」として許可したいのかで、判定方法は変わります。
さらに、NaN、Infinity、空文字、空白だけの文字列、16進数表記、指数表記など、初心者が見落としやすいケースもあります。この記事では、まず「何を数値と呼ぶのか」を整理し、そのうえで実務向けの判定関数を段階的に作っていきます。
最初に整理する:「数値かどうか」には3種類ある
実務で混乱しやすい原因は、「数値」という言葉が、複数の意味で使われることです。まずは、次の3つを分けて考えると整理しやすくなります。
- JavaScriptの値として、すでに数値型であるか。
- 文字列だが、数値として読み取れる形をしているか。
- 金額、数量、整数、0以上など、業務ルールを満たす数値か。
たとえば、123 は数値型です。"123" は数値型ではありませんが、数値として解釈できる文字列です。さらに -10 は数値ですが、「個数は0以上」という業務ルールには合いません。
つまり、型の判定、変換できるかの判定、業務条件の判定を混同しないことが重要です。
ステップ1:まずはJavaScriptの数値型かどうか判定する
typeof で数値型かを確認する
JavaScriptで値の型を調べる基本は typeof です。数値型なら "number" が返ります。
// 値の型を確認する基本例
console.log(typeof 123); // "number"
console.log(typeof 3.14); // "number"
console.log(typeof "123"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof null); // "object"
JavaScriptこれだけ見ると、typeof value === "number" で十分に見えます。しかし、ここには大きな注意点があります。
NaN と Infinity も number 型である
NaN は「Not-a-Number」という名前ですが、JavaScriptでは数値型です。また、Infinity と -Infinity も数値型です。
// どれも typeof は "number" になる
console.log(typeof NaN); // "number"
console.log(typeof Infinity); // "number"
console.log(typeof -Infinity); // "number"
JavaScriptつまり、typeof value === "number" だけでは、「有限の通常の数値かどうか」は判定できません。業務で扱う金額や件数などでは、NaN や Infinity を許可しないことがほとんどです。
ステップ2:有限の数値かどうかを判定する
Number.isFinite() を使う
業務で最もよく使いやすい基本判定は、Number.isFinite() です。これは、値が数値型であり、かつ NaN や Infinity ではない場合にだけ true を返します。
// 有限の数値だけを true にする
console.log(Number.isFinite(123)); // true
console.log(Number.isFinite(3.14)); // true
console.log(Number.isFinite(NaN)); // false
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite("123")); // false
console.log(Number.isFinite(null)); // false
JavaScriptこの関数の良いところは、"123" のような文字列を勝手に数値とみなさないことです。型の厳密さを保ちたい業務コードでは、まずこれを基本に考えると安全です。
グローバルの isFinite() との違い
似た名前の isFinite() というグローバル関数もありますが、こちらは引数を数値へ変換してから判定します。そのため、初心者向けの実務コードでは、意図しない通過が起こりやすいです。
// グローバルの isFinite() は自動変換する
console.log(isFinite("123")); // true
console.log(isFinite("")); // true
console.log(isFinite(" ")); // true
console.log(isFinite(null)); // true
<br>
// Number.isFinite() は型も厳密に確認する
console.log(Number.isFinite("123")); // false
console.log(Number.isFinite("")); // false
console.log(Number.isFinite(" ")); // false
console.log(Number.isFinite(null)); // false
JavaScriptisFinite("") が true になるのは、空文字が数値変換で 0 になるためです。これはフォーム入力の検証などでは非常に危険です。実務では、特別な理由がない限り Number.isFinite() を優先するほうがわかりやすくなります。
ステップ3:文字列として数値を受け取りたい場合を考える
フォーム入力やCSVでは、値が文字列で渡されることがよくあります。そのため、"123" や "3.14" を「数値として使える入力」として扱いたい場面があります。
ただし、ここで大切なのは、「文字列をそのまま数値型と判定する」のではなく、「数値へ安全に変換できるか」を確認するという考え方です。
Number() で変換を試す
文字列を数値へ変換する代表的な方法の1つが Number() です。
// 文字列を数値へ変換する
console.log(Number("123")); // 123
console.log(Number("3.14")); // 3.14
console.log(Number("-10")); // -10
console.log(Number("1e3")); // 1000
console.log(Number("")); // 0
console.log(Number(" ")); // 0
console.log(Number("abc")); // NaN
JavaScriptここで特に注意したいのは、空文字や空白だけの文字列が 0 になることです。これは業務入力の検証では、ほとんどの場合で望ましくありません。
空文字・空白を先に除外する
そのため、文字列を数値として受け入れる関数では、先に trim() で前後の空白を除去し、空になったら不正とするのが実務的です。
// 文字列が数値として読めるかを簡単に判定する
function isNumericString(value) {
// 文字列以外は受け付けない
if (typeof value !== "string") {
return false;
}
// 前後の空白を除去する
const trimmed = value.trim();
// 空文字は数値として扱わない
if (trimmed === "") {
return false;
}
// 数値へ変換し、有限か確認する
return Number.isFinite(Number(trimmed));
}
console.log(isNumericString("123")); // true
console.log(isNumericString(" 3.14 ")); // true
console.log(isNumericString("")); // false
console.log(isNumericString(" ")); // false
console.log(isNumericString("abc")); // falseJavaScriptこの形にすると、フォーム入力やCSVの値を扱うときに、空欄と数値入力を区別しやすくなります。
ステップ4:parseInt() や parseFloat() を判定用途に使いすぎない
初心者がよく使うのが parseInt() や parseFloat() ですが、これらは「先頭から読めるところまで読む」関数です。そのため、厳密な入力チェックには向かない場合があります。
// 途中まで読めれば数値として返してしまう
console.log(parseInt("123abc", 10)); // 123
console.log(parseFloat("3.14xyz")); // 3.14
console.log(parseInt("08", 10)); // 8
JavaScriptたとえば、数量入力として "123abc" を不正にしたいなら、parseInt() の結果だけで判断してはいけません。入力全体が数値として妥当かを見たいなら、まずは Number() と明示的な条件分岐で考えるほうが安全です。
parseInt() や parseFloat() は、「先頭の数値部分だけ抜き出したい」という用途では有効ですが、「数値として正しい入力か」の判定とは役割が異なります。
ステップ5:何を許可するかを業務ルールとして決める
ここまでで、次の2つの基本パターンが見えてきます。
- すでに数値型で、通常の有限数だけを許可したい。
- 文字列も受け付け、数値へ変換できるなら許可したい。
さらに実務では、次のような条件が追加されることが多いです。
- 整数だけを許可する。
- 0以上だけを許可する。
- 1以上100以下の範囲だけを許可する。
- 小数点以下2桁までを許可する。
つまり、数値判定の関数は1個だけで万能にしようとするより、基本の判定関数と、用途別の条件チェックを分けるほうが保守しやすくなります。
業務で使える基本テンプレート その1:有限の数値型か判定する
まずは、JavaScriptの値として、通常の有限数だけを許可する関数です。内部計算やAPIレスポンスの検証などで使いやすい形です。
/**
* 値が有限の数値型かを判定します。
*
* @param {unknown} value 判定対象の値
* @returns {boolean} 有限の数値型なら true
*/
function isFiniteNumber(value) {
// 数値型であり、NaN や Infinity ではない場合だけ true
return Number.isFinite(value);
}
console.log(isFiniteNumber(123)); // true
console.log(isFiniteNumber(3.14)); // true
console.log(isFiniteNumber(NaN)); // false
console.log(isFiniteNumber(Infinity)); // false
console.log(isFiniteNumber("123")); // falseJavaScriptこの関数は短いですが、業務コードでは非常に使いやすいです。「型が number で、通常の計算に使える値だけを許可する」という意図が明確だからです。
業務で使える基本テンプレート その2:数値として読める文字列か判定する
次に、フォーム入力やCSVなど、文字列で受け取る数値を判定する関数です。
/**
* 値が「数値として読める文字列」かを判定します。
*
* 仕様:
* - 文字列だけを受け付けます。
* - 前後の空白は無視します。
* - 空文字や空白だけの文字列は false にします。
* - Number() で有限数へ変換できる場合だけ true にします。
*
* @param {unknown} value 判定対象の値
* @returns {boolean} 数値文字列なら true
*/
function isNumericString(value) {
// 文字列以外は受け付けない
if (typeof value !== "string") {
return false;
}
// 前後の空白を除去する
const trimmed = value.trim();
// 空文字は数値として扱わない
if (trimmed === "") {
return false;
}
// 数値へ変換し、有限数かを確認する
return Number.isFinite(Number(trimmed));
}
console.log(isNumericString("123")); // true
console.log(isNumericString(" 3.14 ")); // true
console.log(isNumericString("-10")); // true
console.log(isNumericString("1e3")); // true
console.log(isNumericString("")); // false
console.log(isNumericString(" ")); // false
console.log(isNumericString("abc")); // false
console.log(isNumericString("123abc")); // falseJavaScriptこの関数は「文字列として入力された数値」を検証する用途に向いています。ただし、指数表記の "1e3" を許可したくない場合などは、別途ルールを追加します。
業務で使える完成版テンプレート:数値判定と用途別ルールを分ける
実務では、基本判定に加えて「整数だけ」「0以上だけ」などの条件が必要になります。そこで、まず文字列または数値を安全に数値へ変換し、その後で個別ルールを判定する形にすると使いやすくなります。
/**
* 値を業務用の数値として正規化します。
*
* 仕様:
* - 数値型は、そのまま使用します。
* - 文字列は trim() 後に Number() で変換します。
* - 空文字、空白だけの文字列、NaN、Infinity は不正とします。
* - 変換できた場合は number を返し、不正な場合は null を返します。
*
* @param {unknown} value 入力値
* @returns {number | null} 正常なら数値、失敗なら null
*/
function toFiniteNumber(value) {
// すでに数値型なら、そのまま有限数か確認する
if (typeof value === "number") {
return Number.isFinite(value) ? value : null;
}
// 文字列なら、前後の空白を除去してから変換する
if (typeof value === "string") {
const trimmed = value.trim();
// 空文字は不正とする
if (trimmed === "") {
return null;
}
const converted = Number(trimmed);
// 有限数なら返し、そうでなければ null
return Number.isFinite(converted) ? converted : null;
}
// それ以外の型は不正
return null;
}
/**
* 値が有限の数値として利用できるか判定します。
*
* @param {unknown} value 入力値
* @returns {boolean} 利用可能な数値なら true
*/
function isUsableNumber(value) {
return toFiniteNumber(value) !== null;
}
/**
* 値が0以上の整数として利用できるか判定します。
*
* @param {unknown} value 入力値
* @returns {boolean} 0以上の整数なら true
*/
function isNonNegativeInteger(value) {
const number = toFiniteNumber(value);
// 正常に変換できなければ false
if (number === null) {
return false;
}
// 整数かつ 0 以上かを確認する
return Number.isInteger(number) && number >= 0;
}
// 基本の利用例
console.log(toFiniteNumber(" 123 ")); // 123
console.log(toFiniteNumber("3.14")); // 3.14
console.log(toFiniteNumber("")); // null
console.log(toFiniteNumber("abc")); // null
console.log(toFiniteNumber(Infinity)); // null
console.log(isUsableNumber("3.14")); // true
console.log(isUsableNumber("abc")); // false
console.log(isNonNegativeInteger("10")); // true
console.log(isNonNegativeInteger("-1")); // false
console.log(isNonNegativeInteger("3.14")); // falseJavaScriptこの設計の利点は、変換のルールが1か所に集まることです。将来「指数表記は許可しない」「全角数字は事前変換する」といった仕様変更があっても、中心となる変換関数を見直すだけで済みやすくなります。
注意が必要なケースを深掘りする
NaN は自分自身と等しくない
NaN は特殊な値で、NaN === NaN が false になります。そのため、value === NaN で判定してはいけません。
// NaN は自分自身と一致しない
console.log(NaN === NaN); // false
// NaN 判定には Number.isNaN() を使う
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("NaN")); // falseJavaScriptただし、業務では NaN 単独を判定するより、Number.isFinite() で「通常の数値か」をまとめて判定するほうがわかりやすい場面が多いです。
空文字や null が 0 として扱われることがある
JavaScriptの自動変換は便利な反面、入力検証では落とし穴になります。
// Number() の変換結果
console.log(Number("")); // 0
console.log(Number(" ")); // 0
console.log(Number(null)); // 0
console.log(Number(false)); // 0
JavaScriptフォームの未入力や欠損値を、意図せず 0 として扱ってしまうと、売上や件数の集計に誤りが入りやすくなります。「変換できるか」より前に、「その入力を受け付けてよいか」を考えることが重要です。
全角数字は自動で通らない
日本語入力では、"123" のような全角数字が入ることがあります。これは Number() で通常の数値へ変換できません。
// 全角数字はそのままでは数値にならない
console.log(Number("123")); // NaN
JavaScriptこれを許可したい場合は、事前に半角へ正規化する処理を別で設計します。ただし、全角の記号や小数点、マイナス記号まで含めてどう扱うかが難しくなるため、入力UI側で制御するほうが簡単な場合も多いです。
BigInt は number とは別の型である
非常に大きな整数を扱う BigInt は、通常の数値型とは別です。
// BigInt は "bigint" 型
console.log(typeof 123n); // "bigint"
// Number.isFinite() では扱わない
console.log(Number.isFinite(123n)); // falseJavaScript金額や件数の通常業務では number で十分なことが多いですが、IDや非常に大きな整数を扱う場合は、最初から別設計にする必要があります。
実務でよくある用途別の判定例
ページ番号:1以上の整数
/**
* ページ番号として妥当か判定します。
*
* @param {unknown} value 入力値
* @returns {boolean} 1以上の整数なら true
*/
function isPageNumber(value) {
const number = toFiniteNumber(value);
if (number === null) {
return false;
}
return Number.isInteger(number) && number >= 1;
}
console.log(isPageNumber("1")); // true
console.log(isPageNumber("0")); // false
console.log(isPageNumber("1.5")); // falseJavaScript金額:0以上の有限数
/**
* 金額として妥当か判定します。
*
* @param {unknown} value 入力値
* @returns {boolean} 0以上の有限数なら true
*/
function isPrice(value) {
const number = toFiniteNumber(value);
if (number === null) {
return false;
}
return number >= 0;
}
console.log(isPrice("1000")); // true
console.log(isPrice("3.14")); // true
console.log(isPrice("-1")); // falseJavaScript在庫数:0以上の整数
/**
* 在庫数として妥当か判定します。
*
* @param {unknown} value 入力値
* @returns {boolean} 0以上の整数なら true
*/
function isStockCount(value) {
return isNonNegativeInteger(value);
}
console.log(isStockCount("0")); // true
console.log(isStockCount("10")); // true
console.log(isStockCount("-1")); // false
console.log(isStockCount("2.5")); // falseJavaScriptこのように、基礎となる変換関数を1つ用意しておくと、用途別の関数を短く、読みやすく作れます。
テストで境界条件を確認する
数値判定の関数は短く見えても、境界条件が多いです。正常な数値だけでなく、空文字、空白、NaN、Infinity、文字列混在、指数表記なども確認します。
// toFiniteNumber() のテスト例
const testCases = [
[123, 123],
[3.14, 3.14],
["123", 123],
[" 3.14 ", 3.14],
["-10", -10],
["1e3", 1000],
["", null],
[" ", null],
["abc", null],
["123abc", null],
[NaN, null],
[Infinity, null],
[-Infinity, null],
[null, null],
[undefined, null],
[true, null],
[false, null],
["123", null]
];
// 期待値と実際の値を比較する
for (const [input, expected] of testCases) {
const actual = toFiniteNumber(input);
console.log({
input,
expected,
actual,
pass: Object.is(actual, expected)
});
}JavaScriptObject.is() を使うと、通常の === よりも一部の特殊値を厳密に比較できます。今回の期待値では主に null や通常の数値を扱っていますが、テストの書き方として覚えておくと便利です。
まとめ
JavaScriptで「数値かどうか」を判定するときは、まず何を数値として扱いたいのかを明確にすることが大切です。数値型の判定、文字列の変換可否、業務ルールの確認は、それぞれ別の段階として考えます。
- 数値型として通常の数を判定するなら、
Number.isFinite()が基本です。 - 文字列を数値として受け取りたいなら、空文字を除外したうえで
Number()とNumber.isFinite()を組み合わせます。 parseInt()やparseFloat()は、厳密な入力検証の中心にしないほうが安全です。NaN、Infinity、空文字、空白、全角数字などの扱いを明示します。- 基本の変換関数と、ページ番号、金額、在庫数などの用途別ルールを分けると保守しやすくなります。
実務で役立つのは、単に「数値かどうか」を判定することではなく、「どの入力を受け付け、どの値を安全に業務処理へ渡すか」を明確にすることです。小さなユーティリティでも、入力条件とテストをそろえることで、安心して再利用できるコードになります。

