-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Conditionally-typed zero
const zeros = ([undefined, null, true, 5, 5n, 'txt', {}, []]).map(x => x ^ x)
console.log(zeros.every(z => z === 0)) // "false"Explanation: The caret ^ is the XOR operator, XOR-ing a value with itself always returns zero, even in JS. But applying XOR to a BigInt (5n in this case) returns a zero of type BigInt.
typeof 0 == 'number' // true
typeof 0n == 'bigint' // trueSo even though BigInt is a numeric-like value, it's not a Number.
The self-XOR is a shorthand for this:
typeof x?.valueOf() == 'bigint' ? 0n : 0Except for the fact that Symbols will cause ^ to throw.
map replaces each element of an iterable (not in-place), every tests a predicate.
BigInt method that only works with Numbers
BigInt.asIntN(8, 257n) // 1n
BigInt.asIntN(8n, 257n) // throws an errorExplanation: The 1st parameter of that static method only accepts Number-typed arguments, more specifically, integer Numbers. That's because it specifies the exponent of the modulo divisor, which is expected to be small.
Links
More pitfalls/footguns/gotchas here: https://github.com/tc39/proposal-bigint#gotchas--exceptions
Spec here: https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-bigint-objects
Docs here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt