For more tips like this, sign up to the weekly newsletter!

Conditionally set an immutable value

Setting an element in a mutable collection does permanent changes, conditionals are therefore easy to do:

let array = [1, 2];

if (condition1) {
  array[0] = 5;
}
if (condition2) {
  array[1] = 6;
}

After this code is run, array is [1, 2], [5, 2], [1, 6], or [5, 6], depending on the two conditions.

But with an immutable collection, variable reassigning is needed to achieve the same effect:

let array = Immutable.List.of(1, 2);

if (condition1) {
  array = array.set(0, 5);
}
if (condition2) {
  array = array.set(1, 6);
}

While this works, it looks wrong and defeats the purpose of immutability.

Use IIFEs

To remedy this, use IIFEs and store each modification in a new constant:

const array = Immutable.List.of(1, 2);

const firstElementSetted = (() => {
  return condition1 ? array.set(0, 5) : array;
})();

const secondElementSetted = (() => {
  return condition2 ? firstElementSetted.set(1, 6) : firstElementSetted;
})();

It is a lot more code, but this approach nicely separates the steps and keeps both the variables and the collection immutable.

Refactoring to normal functions also promote reusability:

const conditionallySetFirstElement = (array, condition) => {
  return condition ? array.set(0, 5) : array;
}
const conditionallySetSecondElement = (array, condition) => {
  return condition ? array.set(1, 6) : array;
}

const array = Immutable.List.of(1, 2);

conditionallySetSecondElement(
  conditionallySetFirstElement(
    array, condition1
  ), condition2
);

Or if you are a fan of functional composition, that ugly pyramid at the end can also be flattened:

const conditionallySetFirstElement = (condition) => (array) => {
  return condition ? array.set(0, 5) : array;
}
const conditionallySetSecondElement = (condition) => (array) => {
  return condition ? array.set(1, 6) : array;
}

// or use lodash.flow or a similar library
const flow = (...funcs) => (val) => {
  return funcs.reduce((v, f) => f(v), val);
}

const array = Immutable.List.of(1, 2);

flow(
  conditionallySetFirstElement(condition1),
  conditionallySetSecondElement(condition2)
)(array);
Try it
Learn more: