Typescript: Less output from optional chaining and null coalescing operator

Created on 23 Oct 2019  ·  2Comments  ·  Source: microsoft/TypeScript

TypeScript Version: 3.8.0-dev.20191023

Search Terms

null coalescing, optional chaining, strict equality operator, loose equality operator, double equal, triple equal

Suggestion

Currently

declare var foo: any;
foo ?? 1;
foo?.bar;

compiles to

var _a;
(foo !== null && foo !== void 0 ? foo : 1);
(_a = foo) === null || _a === void 0 ? void 0 : _a.bar;

This results in redundant !== null && foo !== void 0 and (_a = foo) === null || _a === void 0 output, strict equality/inequality checks cannot be optimized further by existing JavaScript minifiers (UglifyJS, Terser, Babel, etc.)

The suggestion is to use == null standard equality check instead of === null and === void 0 strict equality checks to produce less output.

Use Cases

Since there aren't supposed to be runtime helpers (#33933) for ?? and ?. operators, this may appreciably reduce the footprint, depending on the source code.

Examples

declare var foo: any;
foo ?? 1;
foo?.bar;

compiles to

var _a;
(foo != null ? foo : 1);
(_a = foo) == null ? void 0 : _a.bar;

Checklist

My suggestion meets these guidelines:

  • [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [x] This wouldn't change the runtime behavior of existing JavaScript code
  • [x] This could be implemented without emitting different JS based on the types of the expressions
  • [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [x] This feature would agree with the rest of TypeScript's Design Goals.
Working as Intended

Most helpful comment

Is not valid to check with == null because, in a browser:

document.all == null // is true
document.all == undefined // is true
document.all === null || document.all === undefined // is false

All 2 comments

Is not valid to check with == null because, in a browser:

document.all == null // is true
document.all == undefined // is true
document.all === null || document.all === undefined // is false

The reason that document.all has this weird behavior is that the developers of the current browsers want tests for its existence to fail, so that the code doing the testing will use a newer, better alternative. For historical reasons, there's lots of old code out there like this.

if (document.all) { 
  // assume we're on old IE and use document.all
} else {
  // use better alternatives here
}

When browsers added support for document.all in order to "unbreak" websites that used it without checking for its existence, they didn't want to regress the behavior of websites that were smart enough to check for it and avoid using it. So, they designed it to pretend not to exist.

Given that, I think it would actually be better for TS to use the simpler == null test both for this and for optional chaining (?.). Hopefully no one would write new code that does such old testing, but if they did, the simpler == null test would give the more desirable behavior.

Was this page helpful?
0 / 5 - 0 ratings