Home > front end >  Why does the TypeScript compiler compile its optional chaining and null-coalescing operators with tw
Why does the TypeScript compiler compile its optional chaining and null-coalescing operators with tw

Time:11-05

Why does the TypeScript compiler compile its optional chaining and null-coalescing operators, ?. and ??, to

// x?.y
x === null || x === void 0 ? void 0 : x.y;

// x ?? y
x !== null && x !== void 0 ? x : y

instead of

// x?.y
x == null ? void 0 : x.y

// x ?? y
x != null ? x : y

?

Odds are that behind the scenes == null does the same two checks, but even for the sake of code length, it seems like single check would be cleaner. It adds many fewer parentheses when using a string of optional chaining, too.

Incidentally, I'm also surprised that optional chaining doesn't compile to

x == null ? x : x.y

to preserve null vs undefined.

CodePudding user response:

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 return void 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.

  • Related