13

When trying to destructure a nested object which could be null, the default value is not being used.

I have accomplished this by destructuring in multiple stages, but would rather do it in a single stage if possible.

const obj = { a: null };
const { a: { b, c } = {} } = obj;

This results in error:
Cannot destructure property 'b' of 'undefined' or 'null'

I would expect b and c to be undefined

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
ut9081
  • 787
  • 6
  • 11
  • 2
    `the default value is not being used` what default values? – AZ_ May 13 '19 at 08:57
  • 1
    How can you destructure something that does not exist? You would have to set the object to be intialized `const obj = { a: { b, c} }` – Michael May 13 '19 at 08:58
  • @AZ_ The default value is denoted by `= {}` on the second line of code. So, if `a` is `undefined`, an empty object will be destructured instead. – ut9081 May 13 '19 at 09:32
  • @Michael That is the purpose of the `= {}`. So if `a` is `undefined`, an empty object will be used for the purpose of the destructuring. – ut9081 May 13 '19 at 09:36
  • Ok, `default` value only assigned if the `property` does not exist(`undefined`). – Naren Sep 10 '21 at 14:42

4 Answers4

13

For the default value to be used, the value which you are destructuring must be undefined.

const obj = { a: undefined };
const { a: { b, c } = {} } = obj;

console.log(b, c)
ut9081
  • 787
  • 6
  • 11
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You can change null to empty object in a temporary object. Using map() on entries of object change null to empty object {} and then convert it to object using Object.fromEntries

const obj = { a: null };
const { a: { b, c } = {} } = Object.fromEntries(Object.entries(obj).map(x => x[1] === null ? {} : x));

console.log(b,c)
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
0

Your code looks like this after transpiling:

var obj = { a: null };
var _obj$a = obj.a;
_obj$a = _obj$a === void 0 ? {} : _obj$a;
var b = _obj$a.b,
    c = _obj$a.c;

Here _obj$a is the temporary variable referencing obj.a. If a default value is provided, it will only check this value against void 0 (or undefined) and not against null

You can still do this using destructuring. But, a traditional null and undefined check is much easier to understand.

let obj = { a: null },
  a = obj.a,
  b, c;

if (typeof a !== "undefined" && a !== null) {
  b = obj.a.b;
  c = obj.a.b;
}
adiga
  • 34,372
  • 9
  • 61
  • 83
0

You can use destructuring twice and get the required output -

const { a = {} } = { a: null }
const { b = '', c = '' } = a || {}