[TypeScript] NaN の判定方法
1. 目的
JavaScript
およびTypeScript
の数値型
の特殊な値であるNaN
について特徴をまとめ、その変換の際に必要な注意点を挙げます。
またNaN
を0
に変換する際の簡単な方法についても述べます。
2. 使用言語
- JavaScript
3. NaN の特徴
NaN は JavaScript 上の値の一種で、JavaScript の数値型
に属し、また TypeScript の型注釈では:number
に属します。
しかし一方で、
グローバルプロパティ NaN は非数 (Not-A-Number) を表す値です。
とあるように 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 が返されます。
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を返す
数値型の値の中で 0
と NaN
は falsy
なので、0
が返されます。
それ以外の数値や Infinity
は truthy
なので、元の x
が返されます。
例えば先述した parseInt()で 数値型に変換してから NaN かどうかを評価する場合などに、簡潔に NaN を排除するためにこの方法を利用できることがあります。
Discussion