This blog post shows how you can conditionally add elements inside Array literals and properties inside object literals.
The following code shows how a boolean cond
determines whether or not the element 'a'
is added to the Array arr
.
const cond = false;
const arr = [
...(cond ? ['a'] : []),
'b',
];
// ['b']
This trick works, because the spread operator (...
) for Array literals does nothing if its operand is an empty Array:
> [...[], 'a']
[ 'a' ]
You can use the proposed spread operator for properties in the same manner. Again, a boolean cond
determines whether the property a
is added to the object obj
:
const cond = false;
const obj = {
...(cond ? {a: 1} : {}),
b: 2,
};
// {b: 2}
The spread operator for object literals does nothing if its operand is an object without enumerable own properties:
> {...{}, a: 1}
{ a: 1 }
Using the spread operator in this manner leads to slightly cryptic code. Here it is again, for ease of reference:
const arr = [
...(cond ? ['a'] : []),
'b',
];
The crypticity can be worth it if you want to create the Array with a single expression.
Less cryptic would be to create the Array with the unconditional elements first and to then conditionally insert elements, via slice()
. But that leads to error-prone code, because you have to manage indices properly (insert the last one of multiple elements first, etc.).
An elegant and self-descriptive solution is to use push()
to construct the Array:
const arr = [];
if (cond) {
arr.push('a');
}
arr.push('b');
A variation of the original approach is to use spread and a helper function:
const arr = [
...insertIf(cond, 'a'),
'b',
];
function insertIf(condition, ...elements) { // (A)
return condition ? elements : [];
}
In line A, the triple dots are the rest operator which collects the remaining arguments in an Array and assigns it to elements
.
Another alternative is to conditionally insert either elements or undefined
s and to then filter the latter values out:
const arr = [
(cond ? 'a' : undefined),
'b',
].filter(x => x !== undefined);
...
)” in “Exploring ES6”