'Why does JavaScript's optional chaining use undefined instead of preserving null?

This is a follow up question I asked incidentally at the end of Why does the TypeScript compiler compile its optional chaining and null-coalescing operators with two checks? As resident TypeScript legend jcalz pointed out in a comment, it does deserve its own question.

// Why does the JavaScript treat
x?.y
// as
x === null || x === void 0 ? void 0 : x.y
// instead of
x === null || x === void 0 ? x : x.y
// ?

When x == null, the latter would preserve null while the former always returns undefined.

Modern browsers support ?. natively, so we can test this behavior.

const test = () => {
  console.log('undefined?.x\t\t==>\t', undefined?.x);
  console.log('null?.x\t\t\t==>\t', null?.x);
  console.log('null?.x === null\t==>\t', null?.x === null);
};

try {
  eval('null?.x');
  test();
} catch {
  console.error('Your browser does not support optional chaining syntax.');
  console.info('While optional chaining is supported by all modern browsers, this will not work in browsers that do not support the syntax.')
  console.warn('😮');
  console.info('Shocking, I know.');
  console.info('Compatibility chart: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#browser_compatibility');
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source