oxc-project/oxc · warning · OxcDiagnostic

Prefer class field declaration over `this` assignment in con

Error message

Prefer class field declaration over `this` assignment in constructor for static values.

What it means

Lint diagnostic from oxlint's `unicorn/prefer-class-fields` rule (main variant). Assigning constant values to `this.x` in the constructor (`this.timeout = 5000;`) is the pre-class-fields way to initialize instance state; class field declarations (`timeout = 5000;`) express it directly on the class, work with subclasses/field ordering, and remove constructor boilerplate. The rule flags `this` assignments of static values in constructors.

Source

Thrown at crates/oxc_linter/src/rules/unicorn/prefer_class_fields.rs:15

use oxc_ast::{
    AstKind,
    ast::{
        AssignmentExpression, AssignmentOperator, ClassElement, Expression, MemberExpression,
        MethodDefinitionKind, PropertyDefinitionType, Statement,
    },
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

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

fn prefer_class_fields_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(
        "Prefer class field declaration over `this` assignment in constructor for static values.",
    )
    .with_help("Declare static values as class fields instead of assigning them to `this` in the constructor.")
    .with_label(span)
}

fn prefer_class_fields_suggestion(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn(
        "Encountered same-named class field declaration and `this` assignment in constructor.",
    )
    .with_help("Replace the class field declaration with the value from `this` assignment.")
    .with_label(span)
}

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

declare_oxc_lint!(

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Move the assignment out of the constructor into a field declaration: `retries = 3;` at class top level.
  2. Run `oxlint --fix` for the mechanical move; review when inheritance is involved.
  3. Keep `this.x = param` assignments (parameter-dependent) — the rule only targets static values; suppress inline for computed-by-side-effect initializers.
  4. Disable the rule if the build target does not support class fields (very old transpiler configs).

Example fix

// before
class Client {
  constructor() {
    this.retries = 3;
    this.cache = new Map();
  }
}

// after
class Client {
  retries = 3;
  cache = new Map();
}
Defensive patterns

Strategy: validation

Validate before calling

// oxlint --filter unicorn/prefer-class-fields src/
// CI gate: oxlint --deny-warnings src/

Prevention

When it happens

Trigger: A constructor containing `this.<name> = <literal or static expression>;` where the value does not depend on constructor parameters — e.g. `constructor() { this retries = 3; this.cache = new Map(); }`. Detected while oxlint walks AssignmentExpression nodes that target `this.X` inside constructors.

Common situations: Classes written before the class-fields proposal (or ported from TypeScript configs with `useDefineForClassFields` concerns). Teams adopting oxlint's unicorn category see this on service/utility classes. Watch version changes: switching `target`/`useDefineForClassFields` in TS alters field semantics (define vs set), so the autofix can change behavior when a parent class defines the same property.

Related errors


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