62

I'm trying to understand how falsy and null values are destructured with default parameters. Here are some examples I've ran:

// #1
const person = { email: 'a@example.com' }
const { email = '' } = person
// email is 'a@example.com'

// #2
const person = { email: '' }
const { email = '' } = person
// email is ''

// #3
const person = { email: false }
const { email = '' } = person
// email is boolean false.  why?!

// #4
const person = { email: null }
const { email = '' } = person
// email is null.  why?!

Is there a shortcut I could write to destructure falsy and null values for #3 and #4 so that my email is an empty string?

AmerllicA
  • 29,059
  • 15
  • 130
  • 154
Kevin
  • 3,441
  • 6
  • 34
  • 40
  • 1
    It would be a real 'why?!' if it defaulted with every falsy value. The question may be a part of XY problem, if `person` is arbitrary input it should be conditioned and validated first according to your rules. – Estus Flask Sep 16 '16 at 00:54
  • Only works if key does not exist in object or exists BUT IS `undefined`, so in `const { a = '' } = {};` AND `const { a = '' } = {a: undefined};` `a` will be the empty string else will be whatever the object has as value, like in your case, a `NULL` – Máxima Alekz Jul 29 '22 at 19:16

1 Answers1

74

Only undefined will cause the default initialiser to run in destructuring and function parameter targets. If you want to fall back to your default for all falsy values, use the good old || operator instead:

const email = person.email || '';

Or target a mutable variable and use logical OR assignment afterwards:

let { email } = person;
email ||= '';
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • But if person is null, then person.email will also be an error. right? – Srikanth Sharma Nov 16 '18 at 12:22
  • 3
    @srikanthsharma Sure, just like when using destructuring – Bergi Nov 16 '18 at 13:11
  • 4
    If case like this, `const person = { name:null, email: null }; const { name = '', email = '' } = person` any simply solution? – foxiris Jan 02 '20 at 03:39
  • @foxiris How does the approach of my answer not work for that? – Bergi Jan 02 '20 at 10:25
  • If an Object has many properties, you need to create many new lines for each property. I'm thinking any solution can avoid this. – foxiris Jan 02 '20 at 10:33
  • 3
    @foxiris If you want many variables, you need to write much code. There's no way around that. If applicable, use a loop instead that handles properties generically. Linebreaks don't matter btw. – Bergi Jan 02 '20 at 10:47
  • @foxiris you destruct as you have done and use `name || ''` while using it. – praveen seela Jun 24 '21 at 06:37
  • Dear @Bergi, thanks for your solution, but [my question](https://stackoverflow.com/q/44138770/6877799) was different. Why the `null` doesn't initialiser?, what was the reason? why the engineer implemented it like this? Please reopen my question and if you know that, answer me. thanks. – AmerllicA Oct 08 '21 at 17:10
  • 1
    @AmerllicA It seems you are looking for [this question](https://stackoverflow.com/q/32725034/1048572) then. See also https://2ality.com/2021/01/undefined-null-revisited.html, https://exploringjs.com/es6/ch_parameter-handling.html#sec_parameter-default-values, https://esdiscuss.org/topic/fwd-undefined-being-treated-as-a-missing-optional-argument – Bergi Oct 08 '21 at 22:38
  • 1
    So am I understanding correctly that the answer is functionally "destructuring will not handle falsy and null values, so you must use alternative methods to handle falsy/null"? It might be worth explicitly saying that instead of providing an answer that no longer destructures (destructuring seems to be the whole point of the question as asked). I'd expect the asker would understand the normal ways in which you can handle falsy values on a direct assignment given the nature of the question. – bsplosion Mar 20 '22 at 16:24