{"record":{"id":"6d30ea1015f93587","repo":"oxc-project/oxc","slug":"using-a-spread-operator-here-creates-a-new-noun","errorCode":null,"errorMessage":"Using a spread operator here creates a new {noun} unnecessarily.","messagePattern":"Using a spread operator here creates a new (.+?) unnecessarily\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/unicorn/no_useless_spread/mod.rs","lineNumber":64,"sourceCode":"    .with_help(\"Consider removing the spread operator.\")\n    .with_label(span)\n}\n\nfn iterable_to_array_in_for_of(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Using a spread operator here creates a new array unnecessarily.\")\n        .with_help(\"`for…of` can iterate over iterable, it's unnecessary to convert to an array.\")\n        .with_label(span)\n}\n\nfn iterable_to_array_in_yield_star(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Using a spread operator here creates a new array unnecessarily.\")\n        .with_help(\"`yield*` can delegate to another iterable, so it's unnecessary to convert the iterable to an array.\")\n        .with_label(span)\n}\n\nfn clone(span: Span, is_array: bool, method_name: Option<&str>) -> OxcDiagnostic {\n    let noun = if is_array { \"array\" } else { \"object\" };\n    OxcDiagnostic::warn(format!(\"Using a spread operator here creates a new {noun} unnecessarily.\"))\n        .with_help(\n            if let Some(method_name) = method_name {\n                format!(\"`{method_name}` returns a new {noun}. Spreading it into an {noun} expression to create a new {noun} is redundant.\")\n            } else {\n\n                format!(\"This expression returns a new {noun}. Spreading it into an {noun} expression to create a new {noun} is redundant.\")\n            }).with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoUselessSpread;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallows using spread syntax in following, unnecessary cases:\n    ///\n    ///   - Spread an array literal as elements of an array literal","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/oxc-project/oxc/blob/a3d33dda7cb69da23db4fcaa2c0c05de61e760a1/crates/oxc_linter/src/rules/unicorn/no_useless_spread/mod.rs#L46-L82","documentation":"Diagnostic from the oxlint rule `unicorn/no-useless-spread`. This variant (`clone`) fires when a single-element spread copies an expression that constant evaluation proves already returns a fresh array or object: `[...foo.map(x => x)]`, `[...Object.keys(foo)]`, `[...foo.slice(1)]`, `[...foo.split('|')]`, `[...Array.from(foo)]`, `[...await Promise.all(foo)]`, `[...new Array(3)]`, `{...(foo ? {a: 1} : {a: 2})}`. The message fills `{noun}` with 'array' or 'object' and the help names the producing method when a short snippet exists. Autofix removes the spread (for `new Array(n)` it appends `.fill()` to preserve holes).","triggerScenarios":"`[...foo.concat(bar)]`, `[...foo.copyWithin(-2)]`, `[...foo.filter(bar)]`, `[...foo.flat()]`, `[...foo.map(bar)]`, `[...foo.toSorted()]`, `[...foo.with(0, bar)]`, `[...Object.values(foo)]`, `[...Array.of()]`, `[...new Array(3)]`, `{...(foo ? Object.entries(obj).reduce(fn, {}) : {a: 2})}`. Not fired for spreading a plain identifier (`[...arr]` is a legitimate shallow clone) or methods whose result type cannot be proven (e.g. `[...array.unknown()]`).","commonSituations":"'Just to be safe' copying around expressions that already allocate (`.map()`, `Object.keys`, `Promise.all`), common in React prop objects and utility code. Hits projects with the oxlint correctness category enabled.","solutions":["Remove the spread: `[...foo.map(x => x * 2)]` -> `foo.map(x => x * 2)`.","Apply the rule's autofix; note `[...new Array(3)]` becomes `new Array(3).fill()`.","Keep the spread when cloning a plain identifier (`[...arr]`) - that case is allowed by design.","If the expression's type is opaque and the clone is deliberate, disable the rule inline."],"exampleFix":"// before\nfunction foo(bar) {\n  return [...bar.map(x => x * 2)];\n}\n\n// after\nfunction foo(bar) {\n  return bar.map(x => x * 2);\n}","handlingStrategy":"validation","validationCode":"# detect spreading expressions that already return fresh arrays/objects\nrg -n --type js -U '\\[\\.\\.\\.(?:\\w+\\.(?:map|filter|concat|slice|splice|flat|flatMap|toSorted|toReversed|toSpliced|with|split)\\(|Object\\.(?:keys|values)\\(|Array\\.(?:from|of)\\(|await Promise\\.(?:all|allSettled)|new Array\\()' src/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Learn which methods already return new containers (map, filter, slice, Object.keys, Promise.all, Array.from).","Use `[...x]` only to shallow-clone a plain identifier that may be an array/set.","Note the `new Array(n)` special case: the fix is `.fill()`, since spread of a holey array also drops holes."],"tags":["lint","oxlint","unicorn","spread","shallow-clone","redundant-copy","correctness"],"backgroundTag":"useless-spread","analyzedSha":"a3d33dda7cb69da23db4fcaa2c0c05de61e760a1","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}