oxc-project/oxc · warning · OxcDiagnostic

Disallow using `Object.assign` with an object literal as the

Error message

Disallow using `Object.assign` with an object literal as the first argument and prefer the use of object spread instead

What it means

Diagnostic from the oxlint `prefer-object-spread` rule. It fires when `Object.assign` is called with an object literal as the first argument, since ES2018 object spread does the same without the intermediate literal mutation semantics (prefer_object_spread.rs:18-27). The help text distinguishes two shapes: spreading into a fresh literal (`for_use_literal` false, `{ ...foo }`) versus rebuilding a literal target (`{ foo: bar }`).

Source

Thrown at crates/oxc_linter/src/rules/eslint/prefer_object_spread.rs:18

use std::cmp::max;

use oxc_allocator::ArenaBox;
use oxc_ast::AstKind;
use oxc_ast::ast::{Expression, ObjectExpression, ObjectPropertyKind, PropertyKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

use crate::{AstNode, ast_util::is_method_call, context::LintContext, rule::Rule};

fn prefer_object_spread_diagnostic(span: Span, for_use_literal: bool) -> OxcDiagnostic {
    let help_message = if for_use_literal {
        "Use an object literal instead of `Object.assign`. eg: `{ foo: bar }`."
    } else {
        "Use an object spread instead of `Object.assign` eg: `{ ...foo }`."
    };
    OxcDiagnostic::warn("Disallow using `Object.assign` with an object literal as the first argument and prefer the use of object spread instead")
        .with_help(help_message)
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct PreferObjectSpread;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow using `Object.assign` with an object literal as the first argument and prefer the use of object spread instead.
    ///
    /// ### Why is this bad?
    ///
    /// When `Object.assign` is called using an object literal as the first argument, this rule requires using the object spread syntax instead. This rule also warns on cases where an `Object.assign` call is made using a single argument that is an object literal, in this case, the `Object.assign` call is not needed.
    ///
    /// ### Examples
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace with spread: `Object.assign({}, a, b)` becomes `{ ...a, ...b }` (auto-fixable).
  2. For the literal-target shape, inline the literal: `Object.assign({ foo: bar }, src)` becomes `{ foo: bar, ...src }`.
  3. Keep Object.assign only when mutating an existing non-literal target is intentional — those calls are not flagged here.
  4. Disable the rule for build targets that lack spread support.

Example fix

// before
const merged = Object.assign({}, defaults, userOptions);

// after
const merged = { ...defaults, ...userOptions };
Defensive patterns

Strategy: validation

Validate before calling

// spread is supported everywhere ES2018+; verify target before enabling
// browserslist: "> 0.5%, not dead, not op_mini all"

Prevention

When it happens

Trigger: Enable the rule and write `Object.assign({}, defaults, overrides)` (literal first arg, spread suggested) or `Object.assign({ foo: bar }, source)` (literal-rebuild suggested). Calls whose first argument is not an object literal, e.g. `Object.assign(target, src)`, are not reported by this message path.

Common situations: Options-merging code written before ES2018 spread; tutorial-style `Object.assign({}, state, patch)` in Redux reducers; runtimes or transpilers lacking spread support (old targets); getters on the source being copied — spread copies values like Object.assign, so semantics match, but note spread does not trigger setters on the target the same way in edge cases.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/6d719f639192475a. Report an issue: GitHub.