Number in JavaScript: one type for every number

Number is the single numeric type in JavaScript. It covers integers and decimals, with the precision limits inherent to floating point.
3 min read
Believemy logo

Most languages separate integers from decimals. JavaScript has only one type, which simplifies a great deal and complicates one thing: the precision of calculations on fractional values.

This is where the famous 0.1 + 0.2 that does not give 0.3 comes from. It is neither a bug nor a quirk of the language, and knowing its origin saves an evening spent staring at a cart total.


Definition

Number is the type representing numbers in JavaScript, integers and decimals alike, as a 64-bit floating point value. It covers integers exactly up to roughly nine quadrillion, a limit exposed by Number.MAX_SAFE_INTEGER.

JAVASCRIPT
console.log(typeof 49, typeof 4.9);   // "number" "number"

console.log(0.1 + 0.2);               // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3);       // false
console.log((0.1 + 0.2).toFixed(2));  // "0.30", a string

console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991

The gap comes from binary representation: some decimals, one tenth among them, have no exact form in base 2, exactly as one third has none in base 10. The error is tiny but real, and it accumulates.

Good to know

For money, the safest practice is to count in cents, therefore in whole numbers, and to divide only when displaying. A total computed in decimal currency eventually produces a phantom cent.


Converting and checking

User input always arrives as a String. Converting it is the first thing to do, and checking the result the second.

CallResult
Number("49")49
Number("49 usd")NaN
parseInt("49 usd", 10)49
Number("")0
Number(null)0

The last two lines are classic traps: a missing value becomes zero without the slightest warning. That is a direct effect of Coercion (type conversion), and the only protection is to test for presence before converting.

JAVASCRIPT
const input = "49 usd";
const value = Number(input);

if (Number.isNaN(value)) {
  console.log("invalid input");
} else {
  console.log(value * 2);
}


Two special values

  • NaN signals an impossible calculation. It equals nothing, not even itself, so only Number.isNaN() detects it reliably.
  • Infinity shows up on division by zero. The language raises no error, it returns this value, which then contaminates every following calculation.


Frequently asked questions

Question

How do I display a price properly?

With Intl.NumberFormat, which handles the currency, the decimal separator and spacing according to the locale. new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(49) returns "$49.00". That beats a toFixed followed by concatenation, which produces the wrong format as soon as the country changes.


Question

What do I do beyond MAX_SAFE_INTEGER?

The BigInt type exists for that: you write 9007199254740993n, with a trailing n. You mostly meet it on identifiers coming from a database, which then have to travel as text rather than as numbers so they are not rounded on the way.


Question

Does toFixed return a number?

No, it returns a string, which surprises many people. Chaining a calculation onto it triggers concatenation instead of addition. If the result feeds another calculation, convert it back with Number(), or better, keep the number and round only at display time. See also Math for rounding that stays numeric.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.