oxc-project/oxc · warning · OxcDiagnostic

Unsafe arithmetic operation on optional chaining

Error message

Unsafe arithmetic operation on optional chaining

What it means

Second diagnostic of no-unsafe-optional-chaining, emitted only when the disallowArithmeticOperators option is enabled. Arithmetic on a possibly-undefined optional chain yields NaN instead of throwing, silently corrupting numeric results (help text: 'This can result in NaN.').

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_unsafe_optional_chaining.rs:26

use oxc_span::Span;
use oxc_syntax::operator::LogicalOperator;
use schemars::JsonSchema;
use serde::Deserialize;

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

fn no_unsafe_optional_chaining_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unsafe usage of optional chaining")
        .with_help("If this short-circuits with 'undefined' the evaluation will throw TypeError")
        .with_label(span)
}

fn no_unsafe_arithmetic_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unsafe arithmetic operation on optional chaining")
        .with_help("This can result in NaN.")
        .with_label(span)
}

#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoUnsafeOptionalChaining {
    /// Disallow arithmetic operations on optional chaining expressions.
    /// If this is true, this rule warns arithmetic operations on optional chaining expressions, which possibly result in NaN.
    disallow_arithmetic_operators: bool,
}

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow use of optional chaining in contexts where the `undefined` value is not allowed.
    ///
    /// ### Why is this bad?

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Default the chain before arithmetic: (cart?.total ?? 0) + shipping.
  2. Guard the object first: if (cart) total = cart.total + shipping.
  3. If NaN propagation is acceptable in your domain, leave "disallowArithmeticOperators": false (default).

Example fix

// before
const grandTotal = cart?.total + shipping;
// after
const grandTotal = (cart?.total ?? 0) + shipping;
Defensive patterns

Strategy: type-guard

Validate before calling

const total = (cart?.total ?? 0) + shipping; // default before arithmetic

Type guard

const isNum = (v: unknown): v is number => typeof v === 'number' && !Number.isNaN(v);

Prevention

When it happens

Trigger: Set "disallowArithmeticOperators": true on the rule in .oxlintrc.json, then write cart?.total + shipping, count?.valueOf() * 2, or (opts?.retries) - 1 without a default.

Common situations: Teams enabling the stricter option over a codebase already doing arithmetic on optional API data; money/count aggregation over maybe-missing objects.

Related errors


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