There's something I find particularly pleasing about chaining my code. I enjoyed it when I wrote a lot of jQuery, and even prior to jQuery, I remember feeling like it was a code super power that I could chain function calls together in JavaScript.

It stands to reason that with arrow functions and a handful of array methods, my inner chaining unicorn is free to run wild. Except, in my case, when I use Array.reduce I typically drop into a multi-line function, ugh!

Prior art

I've found that I have a lot of this type of reduce in my code:

return input.reduce((acc, curr) => {
  acc[curr] = altSource[curr];
  return acc;
}, {});

And this:

return input.reduce((acc, curr) => {
  acc.push(curr);
  return acc;
}, []);

Or this, as a poor way to dedupe:

return input.reduce((acc, curr) => {
  if (!acc.includes(curr)) {
    acc.push(curr);
  }

  return acc;
}, []);

Note that these variables are simplified - but it is the same two lines over and over.

To get my chaining all sleek looking, it wants to be in a single line, so what I need are operations that return the updated result. So Array.push is off the list for instance.

Keyed object to array

Instead of:

Reducing array to key lookup

Instead of:

Object.keys(process.env).reduce((acc, curr) => {
  acc[curr] = JSON.stringify(process.env[curr]);
  return acc;
}, {})

Using a Map instead:

Object.keys(process.env).reduce((acc, curr) =>
  acc.set(curr, JSON.stringify(process.env[curr])),
new Map())

Instead of:

const props = Object.getOwnPropertyNames(this).reduce((acc, curr) => {
  if (!curr.startsWith('_')) {
    acc[curr] = this[curr];
  }
  return acc;
}, {});

Should be:

const props = Object.getOwnPropertyNames(this)
  .filter(k => !k.startsWith('_'))
  .reduce((acc, curr) => ({ ...acc, [curr]: this[curr] }), {});

But sometimes being verbose is okay.

For instance, this:

const config = {
  "snippets.javascript": {
    "cl": "console.log($0);",
    "fn": "() => { $0 }"
  },
  "snippets.css": {},
  "snippets.html": {}
};

const res = Object.keys(res).reduce((acc, curr) => {
  const [store, key] = curr.split('.');

  if (!acc[store]) acc[store] = {};
  acc[store][key] = config[curr];
  return acc;
}, {});

Makes the following object:

{
  "snippets": {
    "javascript": {
      "cl": "console.log($0);",
      "fn": "() => { $0 }"
    },
    "css": {},
    "html": {}
  }
}

Could be rewritten as:

const res = Object.keys(config)
  .map(k => [ ...k.split('.'), k ])
  .reduce((acc, [store, key, target]) => (
    { ...acc, [store]: { ...(acc[store] || {}), [key]: config[target] } }
  ), {});

Which is pretty much illegible.

Drafts may be incomplete or entirely abandoned, so please forgive me. If you find an issue with a draft, or would like to see me write about something specifically, please try raising an issue.