Javascript

Why does typeof NaN return number

19 September 2026 · 10 min read

Why does typeof NaN return number

Have you ever been coding in JavaScript and stumbled upon the curious case of NaN? It stands for “Not a Number,” which seems straightforward enough. But then, you use the typeof operator to check its type, and JavaScript confidently declares it a ’number’. This peculiar behavior often leaves developers scratching their heads, wondering why typeof NaN returns ’number’. In this article, we’ll delve into the reasons behind this seemingly contradictory outcome, exploring the historical context, the IEEE 754 standard, and practical implications for your code. We will also touch upon JavaScript’s type system and the quirks that make it unique. Understanding this nuance is crucial for writing robust and error-free JavaScript code, especially when dealing with user input or complex calculations.

The History of NaN and IEEE 754

The story behind NaN begins with the IEEE 754 standard, a technical standard for floating-point arithmetic established in 1985. This standard aimed to unify how different computer systems represent and handle floating-point numbers, ensuring consistent results across platforms. One of the key aspects of this standard is the introduction of NaN to represent the result of invalid or undefined numerical operations. Think of situations like dividing zero by zero (0/0) or taking the square root of a negative number. These operations don’t yield a meaningful numerical result, so NaN steps in as a placeholder. This standardization was crucial for interoperability and predictability in numerical computations across different hardware and software environments.

According to the IEEE 754 standard, NaN is technically a floating-point number, even though it signifies an undefined or unrepresentable value. This is why JavaScript, adhering to the standard, classifies NaN as a ’number’. It’s not an ideal number, of course, but it falls within the broad category of numeric data types. The standard defines several types of NaN, including signaling NaN and quiet NaN, which can be used to handle exceptions and propagate error information through calculations. For example, a quiet NaN will propagate through calculations without raising an exception, while a signaling NaN might trigger an exception handler. This nuanced approach allows for more controlled error handling in numerical computations. According to the IEEE, the goal was to allow operations to continue even after an error and provide a way to detect errors later. IEEE 754 Standard is essential for cross platform interoperability.

So, while it seems counterintuitive that “Not a Number” is considered a ’number’, it’s a direct consequence of the IEEE 754 standard’s design. The standard prioritizes consistent representation and handling of exceptional numerical cases, even if it leads to some semantic oddities in programming languages like JavaScript. The intent was to handle errors gracefully and consistently across systems. This decision has had a lasting impact on how numerical computations are performed in modern computing, influencing everything from hardware design to software development.

JavaScript’s Type System and NaN

JavaScript’s type system is dynamically typed, meaning that the type of a variable is determined at runtime, not during compilation. This flexibility comes at a price: unexpected type-related behaviors, such as typeof NaN returning ’number’. Unlike statically typed languages like Java or C++, JavaScript doesn’t enforce strict type checking, allowing for more implicit type conversions and potentially leading to runtime errors that might have been caught earlier in a statically typed environment.

The fact that NaN is classified as a ’number’ in JavaScript highlights this dynamic nature. JavaScript’s type system is designed to be forgiving, attempting to convert values to the appropriate type whenever possible. In the case of NaN, JavaScript recognizes that it arises from numerical operations, even if those operations result in an undefined numerical value. Therefore, it classifies it as a ’number’ to maintain consistency within the numeric data type. This decision, while seemingly illogical, simplifies certain aspects of JavaScript’s internal workings. Further, JavaScript’s dynamic typing can sometimes obscure the source of NaN values, making debugging more challenging. For instance, a variable might unexpectedly become NaN due to an earlier implicit type conversion gone awry. This underscores the importance of careful type checking and validation in JavaScript code.

Here’s a featured snippet-optimized paragraph: The typeof NaN returning ’number’ in JavaScript is a direct consequence of the IEEE 754 standard, which defines NaN as a special floating-point value representing undefined or unrepresentable numerical results. While it might seem contradictory, this classification aligns with the standard’s goal of consistent error handling and interoperability across different systems. Therefore, JavaScript adheres to this standard, classifying NaN as a ’number’ despite its semantic meaning. This is an important concept to grasp when doing math in Javascript.

Detecting NaN in JavaScript

Because NaN has unique properties, standard equality checks won’t work. Specifically, NaN is the only value in JavaScript that is not equal to itself (NaN !== NaN evaluates to true). This quirkiness makes it essential to use specific methods to reliably detect NaN values. The most common and reliable way to check for NaN is using the isNaN() function. However, the original isNaN() function has some quirks of its own, as it attempts to convert its argument to a number before testing, potentially leading to false positives.

To address the shortcomings of the original isNaN() function, ECMAScript 2015 (ES6) introduced Number.isNaN(). This method provides a more accurate and predictable way to check for NaN because it doesn’t perform any type coercion. It only returns true if the value is strictly equal to NaN. Using Number.isNaN() is generally recommended for modern JavaScript development because it avoids the pitfalls of the older isNaN() function. This ensures that you’re only identifying actual NaN values, rather than values that can be coerced into NaN. For example, isNaN(“hello”) returns true because “hello” can be coerced to NaN, while Number.isNaN(“hello”) returns false because “hello” is not strictly NaN. According to MDN Web Docs, Number.isNaN() is the preferred method for NaN checks.

Here’s a simple example illustrating the difference:

  1. Use isNaN() to check if a variable is NaN. Be aware of potential type coercion.
  2. Use Number.isNaN() for a more accurate check without type coercion.
  3. Test both methods with various inputs to understand their behavior.
  • isNaN(“hello”) returns true (due to type coercion).
  • Number.isNaN(“hello”) returns false (no type coercion).

Practical Implications and Best Practices

Understanding why typeof NaN returns ’number’ is not just an academic exercise; it has practical implications for writing robust and reliable JavaScript code. When dealing with numerical computations, user input, or data from external sources, you need to be vigilant about the possibility of encountering NaN values. Failing to properly handle NaN can lead to unexpected behavior, incorrect calculations, and even application crashes. Therefore, implementing robust error handling and validation mechanisms is crucial.

One common scenario where NaN can arise is when parsing user input. If a user enters non-numeric data into a form field expecting a number, the parsing function (e.g., parseInt() or parseFloat()) will return NaN. Another common source of NaN is mathematical operations with undefined or invalid values. For example, dividing by zero or taking the square root of a negative number will result in NaN. In such cases, you should always validate the input data before performing any calculations to prevent NaN from propagating through your code. Libraries like Lodash offer utility functions to help with input validation. Lodash provides some excellent tools for data validation.

Here are some best practices for handling NaN in JavaScript:

  • Always validate user input to ensure it’s in the expected format before performing numerical operations.
  • Use Number.isNaN() for reliable NaN detection.
  • Implement error handling to gracefully handle NaN values and prevent them from causing application crashes.
Infographic here
FAQ ---
Why does NaN !== NaN evaluate to true?
This is because NaN represents an undefined or unrepresentable value, and by definition, it is not equal to any other value, including itself.
Is isNaN() the same as Number.isNaN()?
No. isNaN() attempts to convert its argument to a number before testing, while Number.isNaN() does not perform type coercion and only returns true if the value is strictly equal to NaN.
How can I prevent NaN from occurring in my code?
Validate user input, handle potential errors in mathematical operations, and use defensive programming techniques to ensure that your code gracefully handles unexpected values.
Understanding why typeof NaN returns 'number' is essential for every JavaScript developer. It highlights the importance of understanding the nuances of the language and the underlying standards that govern its behavior. By using Number.isNaN() and validating your inputs, you can avoid many of the common pitfalls associated with NaN. Remember, while NaN might seem like a strange quirk, it serves a valuable purpose in representing undefined numerical results, allowing your code to handle errors gracefully and consistently. If you want to further explore JavaScript's quirks and improve your coding skills, consider diving deeper into type coercion or exploring other edge cases. You can also [check out our other blog posts](https://courthousezoological.com/n7sqp6kh?key=e6dd02bc5dbf461b97a9da08df84d31c) for more insights.

Question & Answer :
Just out of curiosity.

It doesn’t seem very logical that typeof NaN is number. Just like NaN === NaN or NaN == NaN returning false, by the way. Is this one of the peculiarities of JavaScript, or would there be a reason for this?

Edit: thanks for your answers. It’s not an easy thing to get ones head around though. Reading answers and the wiki I understood more, but still, a sentence like

A comparison with a NaN always returns an unordered result even when comparing with itself. The comparison predicates are either signaling or non-signaling, the signaling versions signal an invalid exception for such comparisons. The equality and inequality predicates are non-signaling so x = x returning false can be used to test if x is a quiet NaN.

just keeps my head spinning. If someone can translate this in human (as opposed to, say, mathematician) readable language, I would be grateful.

[addendum 2023/06] I’ve create a small module for checking the type of anything in ES. It may be helpful, check it @GitHub

Well, it may seem a little strange that something called “not a number” is considered a number, but NaN is still a numeric type, despite that fact :-)

NaN just means the specific value cannot be represented within the limitations of the numeric type (although that could be said for all numbers that have to be rounded to fit, but NaN is a special case).

A specific NaN is not considered equal to another NaN because they may be different values. However, NaN is still a number type, just like 2718 or 31415.


As to your updated question to explain in layman’s terms:

A comparison with a NaN always returns an unordered result even when comparing with itself. The comparison predicates are either signalling or non-signalling, the signalling versions signal an invalid exception for such comparisons. The equality and inequality predicates are non-signalling so x = x returning false can be used to test if x is a quiet NaN.

All this means is (broken down into parts):

A comparison with a NaN always returns an unordered result even when comparing with itself.

Basically, a NaN is not equal to any other number, including another NaN, and even including itself.

The comparison predicates are either signalling or non-signalling, the signalling versions signal an invalid exception for such comparisons.

Attempting to do comparison (less than, greater than, and so on) operations between a NaN and another number can either result in an exception being thrown (signalling) or just getting false as the result (non-signalling or quiet).

The equality and inequality predicates are non-signalling so x = x returning false can be used to test if x is a quiet NaN.

Tests for equality (equal to, not equal to) are never signalling so using them will not cause an exception. If you have a regular number x, then x == x will always be true. If x is a NaN, then x == x will always be false. It’s giving you a way to detect NaN easily (quietly).