Checking if a value is a number in Javascript with isNaN()
Tags: javascript, webdev, tutorial, typescript
Published: 2023-02-05 21:51:17

In Javascript, we have numerous ways to check if something is or is not a number. This is a particularly common task in Javascript, where there is dynamic typing, resulting in some unexpected things being classified as numbers. [Typescript](https://fjolt.com/category/typescript) fixes some of these issues, but in this guide we'll cover how to check if something is a number in Javascript, and the pitfalls you should avoid when trying to do that.

## Introducing isNaN
`NaN` is a special value in Javascript which stands for "Not a Number". If you try to parse a text string in Javascript as an `int`, you'll get NaN:
```javascript
let x = parseInt("hello") // Returns NaN
```

`NaN` in itself is kind of confusing, and you don't always get results you would expect. `NaN`, for example, does not equal any other value, including itself. Testing this out will always return false:
```javascript
5 === NaN // false
NaN === NaN // false
"foo" === NaN // false
```

You might think this all makes sense, until you try to run `typeof NaN` - which returns `number`. So it turns out, that `NaN` is of type 'number' in Javascript after all:
```javascript
typeof NaN // 'number'
```

Ignoring these peculiarities, Javascript comes with a built in function to test if something is "not a number" known as `isNaN`. This function can easily be used to determine if a something would evaluate to `NaN` if it was run through something like `parseFloat`:
```javascript
isNaN("hello") // true
isNaN(5) // false
isNaN({}) // true
isNaN(() => {}) // true
```

Since `isNaN` checks if something is not a number, we can use `!isNaN` to test if something is a number. For example, `!isNaN(5)` is an easy way to test if `5` is a number:
```javascript
!isNaN(5)
```

`isNaN` makes sense in most cases, but since it parses numbers, it can cause some unexpected side effects. For example, `Number(1n)` on `BigInt` types throws an error, and therefore throws an error on `isNaN` too:
```javascript
isNaN(1n) // throws error
```

To resolve some of these problems, Javascript just made a new method, called `Number.isNaN`. It's mostly the same, only it won't coerce the type to a number.

## Number.isNaN vs isNaN
They are commonly thought to be the same, but `isNaN` and `Number.isNaN` work differently. `isNaN` essentially parses the input, and tries to make a number out of it. That's why you see problems when you try to do `isNaN(1n)`, since `Number(1n)` throws an error. Instead, you can use `Number.isNaN()`

The difference between `isNaN` and `Number.isNaN` is that `Number.isNaN` does not try to coerce the input into a number. Unlike `isNaN`, it simply takes the input and confirms if it is equal to `NaN` or not. That makes 

So all of the following will return false, since none of them are exactly equal to `NaN`:
```javascript
Number.isNaN({}) // false
Number.isNaN("hello") // false
Number.isNaN(() => {}) // false
Number.isNaN("5") // false
```

while the following will return true, since they do return `NaN`:
```javascript
Number.isNaN(5 / "5") // true
Number.isNaN(parseFloat("hello")) // true
```

Either `Number.isNaN` or `isNaN` will solve most of your number checking needs, but there is one additional way to check if something is a number in Javascript

## Using isInteger and isSafeInteger to check a number in Javascript
As well as `isNaN` and `Number.isNaN`, the methods `Number.isInteger` and `Number.isSafeInteger` can help you determine if something is simply an integer, with no decimal points. Just like `Number.isNaN`, both of these methods do not try to evaluate the contents as a number. That means passing in a string will always return false, while a normal integer will pass the test:
```javascript
Number.isInteger("5") // false
Number.isInteger(5) // true
Number.isSafeInteger("5") // false
Number.isSafeInteger(5) // true
```

`isSafeInteger` differs from `isInteger` by checking that the number falls outside the `bigint` range - i.e. within `-2^53` and `2^53` - so for most use cases `isInteger` will do the job.

## Using typeof to check if something is a number in Javascript
The final way to check if something is a number is to use `typeof` - again, this may fit your needs better for some cases, since `typeof Math.sqrt(-1)` returns `number`, rather than `NaN` - however things like `1n` will still show a type of `bigint`:
```javascript
typeof Math.sqrt(-1) // 'number'
typeof parseFloat("35") // 'number'
typeof 35 // 'number'
typeof 1n // 'bigint'
```

However, **be careful** since it is quite unreliable. Since `typeof NaN` returns `number`, you can run into some unexpected situations which you will generally want to avoid. As such, `Number.isNaN` remains probably the best way to check if something is or isn't a number.

Here are a few unexpected `typeof` situations you'll generally want to avoid:
```javascript
typeof parseFloat("hello") // 'number' - since NaN is a number
typeof 5 / "5" // 'NaN' - since this evaluates typeof 5, and then divides by "5"
typeof (5 / "5") // 'number' - since this evaluates as NaN, which is a number
typeof NaN // 'number' - since NaN is of type number
typeof "5" // 'string'
```

## Conclusion
Checking if something is or is not a number in Javascript has some complexities, but it's generally straight forward. The key points are:
- `isNaN` is commonly used, but will evaluate its input as a number, which may cause some inputs are incorrectly judged to be `NaN` or throw an error.
- `Number.isNaN` is a robust version of `isNaN`, which checks if something is exactly equal to `NaN`. It does not evaluate its contents as a number
- `typeof` can tell you if something is a `number` or not, but it may lead to some unexpected situations, since `NaN` is also of type number.

I hope you've enjoyed this guide on checking if something is a number in Javascript. [You can also check out more of my Javascript content here](https://fjolt.com/category/javascript).