unicorn/no-useless-spread

Disallow spreads that only build an array or object to take it apart or copy it again

fixable

A spread that changes nothing costs an extra array or object and makes the line harder to read. The rule reports three kinds.

  • A literal spread into a literal or a call: [...[a, b], c], { ...{ a }, b }, save(...[a, b]). Write the elements directly.
  • An iterable turned into an array for something that takes any iterable: for...of, yield*, new Set(), new Map(), typed array constructors, Array.from(), Object.fromEntries(), Promise.all(), Promise.allSettled(), Promise.any(), Promise.race().
  • A copy of a value that's already new: [...items.map(fn)], [...text.split(",")], [...Object.keys(user)], { ...Object.fromEntries(entries) }.

--fix removes the spread in most cases. It doesn't touch for...of and yield*.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"unicorn/no-useless-spread" = "error" # or "warn"

Examples#

example.js3 problems
const colors = [...["red", "green"], extra];
const config = { ...{ debug: false }, ...overrides };
log(...["saved", file]);
example.js2 problems
const unique = new Set([...names]);

for (const entry of [...map.entries()]) {
  visit(entry);
}
example.js2 problems
const upper = [...names.map(name => name.toUpperCase())];
const results = [...(await Promise.all(jobs))];
example.jsNo problems
const colors = ["red", "green", extra];
const config = { debug: false, ...overrides };
log("saved", file);

const unique = new Set(names);

for (const entry of map.entries()) {
  visit(entry);
}

const upper = names.map(name => name.toUpperCase());
const results = await Promise.all(jobs);

Copying a variable is a real copy, and so is turning an iterable into an array to keep it:

example.jsNo problems
const copy = [...names];
const clone = { ...user };
const keys = [...map.keys()];