Just imagine, your APIs are returning a huge number like 900719925474099999, but after JSON parsing the response, you received 900719925474100000. Isn’t it weird to see something change after a simple parsing?
let x=900719925474099999;
console.log(x); // Console: 900719925474100000
let y=900719925474099999n;
console.log(y); // Console: 900719925474099999
This is going to have a huge impact on business and computation. We recently faced this situation. And appending n at the end of the number will solve this issue. But how can we expect a JSON number to have n at the end?
Let’s find out:
- What is happening here in the background?
- Why appending n at the end solving this issue?
- How have we handled it for our use case?
- What are some of the best and most practical ways to handle this situation?
Introduction
Javascript uses a common number type for integer and float types. In JavaScript, all numbers are stored in a 64-bit floating-point format (IEEE 754 standard). As a result, the number type can support a range of numbers between -(2⁵³-1) and (2⁵³-1). This range is defined by two constants Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER. Any number beyond this can’t be handled by Javascript accurately.
In our case, 900719925474099999 is way beyond the Number.MAX_SAFE_INTEGER, can’t be represented by the Javascript number type, so it rounded off to 900719925474100000.
Then, How does it even work when we append n at the end of the number?
Introducing BigInt in Javascript
Javascript has a special data type, BigInt, to handle integers or floats beyond the range of Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER. As an untyped language, Javascript interprets the variable type from the provided value. To represent a BigInt, we’ve to append n at the end of the value. Otherwise, it’ll be considered as a number type.
With BigInt the total number of supported data types in JavaScript is 8:
String, Number, Bigint, Boolean, Undefined, Null, Symbol, Object
Why isn’t everything a BigInt?
One common question everyone gets is, if javascript treats every integer or float as BigInt, this issue might not even arise in the first place.
Well, this is not an optimal solution. Javascript is primarily rendered on the client machine, which may have limitations in terms of memory usage. Making every integer a BigInt requires a severe amount of memory and may result in excess memory usage that is not even required.
How to create BigInt?
BigInt was first introduced in ECMAScript 2020; BigInt provides a way to represent and manipulate arbitrarily large integers. To create a BigInt:
- BigInt literal: Append an n to the integer literal
- BigInt constructor: Use BigInt()
const largeNumber = 9007199254740992n; // BigInt literal
const anotherLargeNumber = BigInt("123456789012345678901234567890"); // BigInt constructor
As an alternative, you may use third-party packages like json-bigint.
In our case, we need that value just for display purposes, so instead of converting it into BigInt, we treated it as a string.
Conclusion
Bigint can handle almost all integers and floats, as it has no limits. In most cases, number type alone is enough. Only go with Bigint if necessary, as it has memory implications. Just try to avoid using BigInt as much as you can.
Have you ever faced this issue with your projects?