example:
I'm going to use 0xC0000000 (32-bit signed complement) for -2^30
const num = Number('0xC0000000')
console.log(num === -Math.pow(2,30)) // expected: true
JavaScript only has two's complement integers in two places:
As a temporary value during some operations. The bitwise operators use 32-bit ints, and some Math object methods work with 32-bit int values (for example, imul).
As an element in a Int16Array, Int32Array, or Int64Array. (Int32Array in your case.)
Otherwise, all numbers are either number (IEEE-754 double-precision binary floating point) or BigInt (arbitrary-precision non-two's-complement integers).
So for instance, you can have a two's complement in a single-element Int32Array.
const array = Int32Array.from([0xC000000]);
console.log(array[0].toString(16));
However, whenever you use that 32-bit integer, it gets converted to number. That said, JavaScript's conversions between number and 32-bit signed int are fairly smart. For example, consider this two's complement boundary condition:
const array = Int32Array.from([0x7FFFFFFF]);
console.log(array[0].toString(16)); // 7fffffff
++array[0];
console.log(array[0].toString(16)); // -80000000
That's what you'd want for a two's complement operation, even though it isn't a two's complement operation (in theory; JavaScript engines are allowed to optimize). The operation is 32-bit two's complement int to number, increment number, convert number back to 32-bit two's complement int. But we still get the desired result.