oxc/no-accumulating-spread
Disallow spreading the accumulator in reduce() and in loops
[...result, item] copies everything in result into a new array. Doing that once per item copies 1 element, then 2, then 3. For 10,000 items, that's about 50 million copied elements instead of 10,000 pushes. Objects built with { ...result, [key]: value } cost the same.
The rule reports:
- In the callback of
reduce()orreduceRight(): a spread of the first parameter, when the callback has exactly two parameters. - In a loop:
result = [...result, item]orresult = { ...result, ... }, whenresultis aletdeclared outside the loop.
Change the accumulator in place instead. When the initial value is a fresh [] or {}, no other code holds it, so nothing else sees the change.
Configure#
Off by default. To turn it on:
bunfig.toml
[lint.rules]
"oxc/no-accumulating-spread" = "error" # or "warn"Examples#
example.js2 problems
const names = users.reduce((result, user) => [...resultDo not spread accumulators in Array.prototype.reduce(), user.name], []);
const byId = users.reduce((result, user) => ({ ...resultDo not spread accumulators in Array.prototype.reduce(), [user.id]: user }), {});example.js1 problem
let activeDo not spread accumulators in loops = [];
for (const user of users) {
if (user.isActive) {
active = [...active, user];
}
}example.jsNo problems
const names = users.map((user) => user.name);
const byId = users.reduce((result, user) => {
result[user.id] = user;
return result;
}, {});
const active = [];
for (const user of users) {
if (user.isActive) {
active.push(user);
}
}When not to use it#
For a handful of items, the cost doesn't matter. If you like how the spread reads and your lists are small, leave the rule off.