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
- Delete the `!!` inside the condition; the context already coerces to boolean.
- Keep `!!` only at assignments that must store a real boolean: `const ok = !!x;`.
- Run `oxlint --fix` to strip redundant casts automatically.
- 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
- Apply `!!` or `Boolean()` only at assignments, never inside a condition.
- Run `oxlint --fix` after merges to strip casts in bulk.
- Write the condition as the expression itself; do not pre-cast it.
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
- `debugger` statement is not allowed
- Variables should not be deleted
- A regular expression literal can be confused with '/='.
- Duplicate class member: {member_name:?}
- Duplicate conditions in if-else-if chain
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/a24ec7b84b84c055.
Report an issue: GitHub.