I had to look this up on the internet so many times during the years that I decided to write this Gist to see if I memorize it once for all (or at least I have a quick place to look next time).
Say your code creates an object and there's a particular property that it sometimes needs to add, sometimes it doesn't. The straightforward way of coding this would be:
const x = {
a: 1
};
if (someCondition) {
x.b = 2;
}
But I find this ugly and verbose. Luckily, JavaScript offers an alternative way of writing it using object destructuring:
const x = {
a: 1,
...(someCondition ? { b: 2 } : {})
};
This is destructuing either { b: 2 }
or {}
depending on someCondition
. Since destructuring {}
results in an empty set of properties, we get exactly what we want. It is even possible to make it shorter by doing:
const x = {
a: 1,
...(someCondition && { b: 2 })
};
The object { b: 2 }
is still only destructured if someCondition === true
. The interesting thing here is that, if the condition is false, the result is ...(undefined)
, which is happily resolved to an empty set.
There is an analogous situation when you want to conditionally add an item to an array that is being created:
let y = [1, 2, ...(someCondition ? [3] : [])];
Here, 3
is pushed into the array only if someCondition === true
, otherwise an empty array is destructured instead, resulting in an empty set again. There is particularity here, though: doing someCondition && [3]
won't work if the condition is false!
Uncaught TypeError: (false && [3]) is not iterable
JavaScript can only destructure iterables as arrays, so the ternary operator is the best we can do.