Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the TypeScript compiler compile its optional chaining and null-coalescing operators with two checks?

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. This has since been answered: Why does JavaScript's optional chaining to use undefined instead of preserving null?

like image 477
dx_over_dt Avatar asked Nov 04 '21 16:11

dx_over_dt


People also ask

Does TypeScript have optional chaining?

In TypeScript, optional chaining is defined as the ability to immediately stop running an expression if a part of it evaluates to either null or undefined .

Does TypeScript have null coalescing operator?

TypeScript 3.7 added support for the ?? operator, which is known as the nullish coalescing operator. We can use this operator to provide a fallback value for a value that might be null or undefined .

Why does TypeScript need to be compiled?

The TypeScript compiler compiles these files and outputs the JavaScript with . js extension by keeping the same file name as the individual input file. The TypeScript compiler also preserves the original file path, hence the . js output file will be generated where the input file was in the directory structure.

What does double question mark mean in TypeScript?

Double question marks(??) or nullish coalescing operator helps us to assign default values to null or undefined variables in Angular and Typescript. It's often called as Null coalescing operator. It's introduced as part of Typescript 3.7 version.


1 Answers

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.

like image 87
jcalz Avatar answered Sep 18 '22 07:09

jcalz