Why does the TypeScript compiler compile its optional chaining and null-coalescing operators with two checks?
Solution 1:
You can find an authoritative answer in microsoft/TypeScript#16 (wow, an old one); it is specifically explained in this comment:
That's because of
document.all
[...], a quirk that gets special treatment in the language for backwards compatibility.document.all == null // true document.all === null || document.all === undefined // false
In the optional chaining proposal
document.all?.foo === document.all.foo
but
document.all == null ? void 0 : document.all.foo
would incorrectly returnvoid 0
.
So there is a particular idiosyncratic deprecated obsolete wacky legacy pseudo-property edge case of type HTMLAllCollection
that nobody uses, which is loosely equal to null
but not strictly equal to either undefined
or null
. Amazing!
It doesn't seem like anyone seriously considered just breaking things for document.all
. And since the xxx === null || xxx === undefined
version works for all situations, it's probably the tersest way of emitting backward-compatible JS code that behaves according to the spec.