oxc-project/oxc · warning · OxcDiagnostic

Optional chain expressions can return undefined by design: u

Error message

Optional chain expressions can return undefined by design: using a non-null assertion is unsafe and wrong.

What it means

Oxlint's no-non-null-asserted-optional-chain: `foo?.bar!` asserts non-null on the result of a chain that by design yields `undefined` when a link is missing. The warn text at no_non_null_asserted_optional_chain.rs:23 calls this unsafe and wrong, and the diagnostic carries two labels: the assertion as primary and the chain as secondary (the two spans in the function signature at lines 14-17).

Source

Thrown at crates/oxc_linter/src/rules/typescript/no_non_null_asserted_optional_chain.rs:19

use oxc_ast::{
    AstKind,
    ast::{ChainElement, Expression, match_member_expression},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

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

fn no_non_null_asserted_optional_chain_diagnostic(
    chain_span: Span,
    assertion_span: Span,
) -> OxcDiagnostic {
    OxcDiagnostic::warn("Optional chain expressions can return undefined by design: using a non-null assertion is unsafe and wrong.")
        .with_help("Remove the non-null assertion.")
        .with_label(assertion_span.primary_label("non-null assertion made after optional chain"))
        .and_label(chain_span.label("optional chain used"))
}

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

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow non-null assertions after an optional chain expression.
    ///
    /// ### Why is this bad?
    ///
    /// By design, optional chain expressions (`?.`) provide `undefined` as the expression's value, if the object being
    /// accessed is `null` or `undefined`, instead of throwing an error. Using a non-null assertion (`!`) to assert the
    /// result of an optional chain expression is contradictory and likely wrong, as it indicates the code is both expecting

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Remove the `!` and let the chain propagate undefined (`foo?.bar?.city`)
  2. Provide a fallback with `??`
  3. Add an explicit early return or throw when the value is undefined
  4. Restructure so the optional link is not needed

Example fix

// before
const city = user?.address!.city;

// after
const city = user?.address?.city;
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint --deny-warnings .

Type guard

function isDefined<T>(value: T | null | undefined): value is T {
  return value !== null && value !== undefined;
}

// usage instead of `user?.address!.city`
const address = user?.address;
if (!isDefined(address)) return;
doWork(address.city);

Prevention

When it happens

Trigger: `foo?.bar!`, `foo?.()!.toString()`, `map.get(k)?.value!` - a postfix `!` applied to the result of an optional chain expression.

Common situations: Developers forcing away 'possibly undefined' compiler errors, then hitting runtime crashes exactly when the chain short-circuits; migration code where nullability was poorly understood.

Related errors


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