🔢

[TypeScript] NaN の判定方法

2024/12/20に公開

1. 目的

JavaScriptおよびTypeScript数値型の特殊な値であるNaNについて特徴をまとめ、その変換の際に必要な注意点を挙げます。

またNaN0に変換する際の簡単な方法についても述べます。

2. 使用言語

  • JavaScript

3. NaN の特徴

NaN は JavaScript 上の値の一種で、JavaScript の数値型に属し、また TypeScript の型注釈では:numberに属します。

しかし一方で、

グローバルプロパティ NaN は非数 (Not-A-Number) を表す値です。

NaN - JavaScript | MDN

とあるように NaN は非数を表します。

JavaScript の 数値型には 0, 4, -2.1 といった一般的な数値の他に2種類の特殊な値が含まれます。

1つはInfinityであり、例えば 1 を 0 で割った場合、この値になります。

もう1つがNaNであり、処理の結果が非数、つまり数値にならない場合にこの値になります。

4. NaN が現れる例

NaN を返す演算には 5 種類があります。

  • 数値が解釈できない (例えば parseInt("blabla") または Number(undefined))
  • 結果が実数にならない数学演算 (例えば Math.sqrt(-1))
  • オペランドが NaN である (例えば 7 ** NaN)
  • 不確定形 (例えば 0 * Infinity または undefined + undefined)
  • 文字列が関わる加算以外の何らかの演算 (例えば "foo" / 3)

NaN - JavaScript | MDN

実際に、上記の例ではすべて NaN が返されます。

console.log(parseInt("blabla")); // NaN
console.log(Number(undefined)); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(7 ** NaN); // NaN
console.log(0 * Infinity); // NaN
console.log(undefined + undefined); // NaN
console.log("foo" / 3); // NaN

また、typeofにより型を判定すると、NaN は確かに 数値型に属しています。

console.log(typeof NaN); // number

実際のアプリ制作の場で出会う例として、API で取得した値に parseInt()や Number()をかけようとしたところ、数値に変換できない文字列や undefined を取得していたために NaN が返ってしまうといった例が挙げられます。

特に文字列が数値に変換可能かを判定する場合はやや複雑な処理が必要になることが多いため、そういった判定をせずに parseInt()をかけてしまってから NaN に対する処理を行った方が記述が簡潔になることがあります。

5. NaN の判別方法

5.1. Number.isNaN()と isNaN()

よく知られている方法としてNumber.isNaN()を使用する方法と、グローバル関数isNaN()を使用する方法があります。

Number.isNaN() - JavaScript | MDN #Number.isNaN() とグローバルの isNaN() の相違点

Number.isNaN()は引数が 数値型の NaN であるかを返します。

当然、引数が 数値型でなかった場合は false を返すことになります。

console.log(Number.isNaN("3")); // false
console.log(Number.isNaN("foo")); // false
console.log(Number.isNaN(undefined)); // false

一方でグローバル関数のisNaN()は引数が 数値型でない場合、数値型に型強制された上で NaN かどうかを評価します。

console.log(isNaN("3")); // false
console.log(isNaN("foo")); // true
console.log(isNaN(undefined)); // true

これにより予想外の値を返すことも多く、公式の MDNでも

isNaN 関数の型強制は意外なものになる可能性があるため、他の Number.isNaN() を使用した方が良いかもしれません。

と言及されており、基本的にNumber.isNaN()が推奨されることが多いです。

5.2. 論理和(||)を使った変換

ある 数値型の変数 x について、NaN の場合は 0 に変換して扱いたい時、以下のように記述することができます。

x || 0; // xがNaNの場合は0、それ以外の場合はxを返す

数値型の値の中で 0NaNfalsy なので、0 が返されます。

それ以外の数値や Infinitytruthy なので、元の x が返されます。

例えば先述した parseInt()で 数値型に変換してから NaN かどうかを評価する場合などに、簡潔に NaN を排除するためにこの方法を利用できることがあります。

参考文献

株式会社ブレイクエッジ 技術ブログ

Discussion