oxc-project/oxc · warning

Redundant double negation

Error message

Redundant double negation

What it means

This diagnostic comes from the `no_extra_boolean_cast` rule in oxlint. It reports a double negation `!!x` in a place where the value is already coerced to a boolean: an `if` test, a loop condition, a ternary test, a logical operand, or under another negation. The rule ships a fixer, so `oxlint --fix` can strip the cast with correct token boundaries. A second message, `Redundant Boolean call`, covers the `Boolean(x)` form.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_extra_boolean_cast.rs:27

    },
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_syntax::{
    operator::{LogicalOperator, UnaryOperator},
    precedence::{GetPrecedence, Precedence},
};

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
    utils::{get_precedence, pad_fix_with_token_boundary},
};

fn no_extra_double_negation_cast_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Redundant double negation")
        .with_help("Remove the double negation as it will already be coerced to a boolean")
        .with_label(span)
}

fn no_extra_boolean_cast_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Redundant Boolean call")
        .with_help("Remove the Boolean call as it will already be coerced to a boolean")
        .with_label(span)
}

#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoExtraBooleanCast {
    /// when set to `true`, in addition to checking default contexts, checks
    /// whether extra boolean casts are present in expressions whose result is
    /// used in a boolean context. See examples below. Default is `false`,
    /// meaning that this rule by default does not warn about extra booleans
    /// cast inside inner expressions.

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Delete the `!!` inside the condition; the context already coerces to boolean.
  2. Keep `!!` only at assignments that must store a real boolean: `const ok = !!x;`.
  3. Run `oxlint --fix` to strip redundant casts automatically.
  4. Suppress with `// oxlint-disable-next-line no-extra-boolean-cast` when the cast is deliberate.

Example fix

// before
if (!!options.verbose) {
  log('starting');
}

// after
if (options.verbose) {
  log('starting');
}
Defensive patterns

Strategy: validation

Validate before calling

// find double negation used inside conditions
if (/(?:if|while)\s*\(\s*!!/.test(src)) console.warn('redundant double negation in condition');

Type guard

const isBoolean = (v: unknown): v is boolean => typeof v === 'boolean';

Prevention

When it happens

Trigger: `if (!!items.length) { ... }`, `while (!!pending) { ... }`, a ternary test `!!x ? a : b`, or a logical operand `x || !!y`. Assignments such as `const ok = !!x;` are boolean-producing spots and stay valid.

Common situations: A C-style habit of double negation. Code moves from a boolean variable assignment into a condition, and the cast travels along. Mixed team styles after a merge.

Related errors


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