oxc-project/oxc · error · OxcDiagnostic

Expected to always call `super()` before `this`/`super` prop

Error message

Expected to always call `super()` before `this`/`super` property access.

What it means

`no-this-before-super` reports accessing `this` or `super` properties in a derived class constructor before `super()` has been called — JavaScript throws `ReferenceError: Must call super constructor in derived class before accessing 'this'` at runtime in exactly this situation. oxlint implements it with control-flow-graph analysis (oxc_semantic CFG, `neighbors_filtered_by_edge_weight`, ErrorEdgeKind) so both straight-line orderings and branches (e.g. `if (x) { this.a = 1 } super();`) are covered.

Source

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

use oxc_ast::{
    AstKind, AstType,
    ast::{Argument, Expression, MethodDefinitionKind},
};
use oxc_cfg::{
    BlockNodeId, ControlFlowGraph, EdgeType, ErrorEdgeKind,
    graph::visit::{EdgeRef, neighbors_filtered_by_edge_weight},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_semantic::NodeId;
use oxc_span::{GetSpan, Span};
use rustc_hash::{FxHashMap, FxHashSet};

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

fn no_this_before_super_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Expected to always call `super()` before `this`/`super` property access.")
        .with_help("Call `super()` before `this`/`super` property access.")
        .with_label(span)
}

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

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Requires calling `super()` before using `this` or `super`.
    ///
    /// This rule can be disabled for TypeScript code, as the TypeScript compiler
    /// enforces this check.
    ///
    /// ### Why is this bad?
    ///
    /// In the constructor of derived classes, if `this`/`super` are used before `super()` calls,

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Move the `super(...)` call to the first statement of the constructor.
  2. If the access is conditional, ensure every path reaching it has already called `super()` (hoist the super call above the branch).
  3. Delete the field initialization from the constructor and use a class field declaration instead — fields initialize after super() automatically.

Example fix

// before
class Btn extends Component {
  constructor(props) {
    this.label = props.label; // ReferenceError at runtime
    super(props);
  }
}

// after
class Btn extends Component {
  constructor(props) {
    super(props);
    this.label = props.label;
  }
}
Defensive patterns

Strategy: validation

Validate before calling

# TypeScript also catches this before runtime: 'super' must be called before accessing 'this'
npx tsc --noEmit

Prevention

When it happens

Trigger: `class A extends B { constructor() { this.x = 1; super(); } }`, calling `super.method()` or reading `this` in any CFG path that reaches the access before the `super()` call node, including inside conditionals or early-return paths.

Common situations: Adding initialization code at the top of a derived constructor and forgetting `super()` must come first; refactoring constructors and moving the `super(...)` call into a branch; subclassing framework base classes (React components, custom elements) where the super call is easy to overlook.

Related errors


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