Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally pushing to an array with spread operator

I am pushing elements to an array based on a condition as explained here http://2ality.com/2017/04/conditional-literal-entries.html

const arr = [
  ...(cond ? ['a'] : []),
  'b',
];

Now, this works fine, but when I try

const arr = [
  ...(cond && ['a']),
  'b',
];

instead, it stops working.

I would like to know why it's not working anymore, and if there is a way to conditionally push using spread operator and && instead of ?.

Thank you

like image 274
user3808307 Avatar asked Feb 14 '18 09:02

user3808307


2 Answers

No, it is not possible, because all iterable objects are truthy.

If cond is falsey, you have a value which is not spreadable by Symbol.iterator

The built-in types with a @@iterator method are:

  • Array.prototype[@@iterator]()
  • TypedArray.prototype[@@iterator]()
  • String.prototype[@@iterator]()
  • Map.prototype[@@iterator]()
  • Set.prototype[@@iterator]()

var cond = false;

const arr = [
  ...(cond && ['a']),  // throws error, function expected
  'b',
];

console.log(arr);
like image 134
Nina Scholz Avatar answered Oct 22 '22 22:10

Nina Scholz


Yes, it's possible. But maybe that's an overkill that performs worse and decreases the readability.

const arr = [];
arr.push(...[false && 'nope'].filter(v => v));
arr.push(...[true && 'yep'].filter(v => v));
arr.push(...[false && 'no', true && 'yes'].filter(v => v));
    
console.info(arr);

As @Nina Scholz indicated an iterable is required for spread operator to work. By using a second array (which may be empty) we can eventually reach the following state (arr.push()).

like image 39
zurfyx Avatar answered Oct 22 '22 20:10

zurfyx