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 expectingView on GitHub (pinned to e1e7af627c)
Solutions
- Remove the `!` and let the chain propagate undefined (`foo?.bar?.city`)
- Provide a fallback with `??`
- Add an explicit early return or throw when the value is undefined
- 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
- Never postfix `!` on anything containing `?.`; treat it as a bug pattern
- Handle the undefined case with `??` or an early return
- Enable strictNullChecks so the short-circuit case is visible in the type
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
- Forbidden non-null assertion.
- extra non-null assertion
- 'Disallow non-null assertions in the left operand of a nulli
- Confusing combinations of non-null assertion and equal test
- Confusing combinations of non-null assertion and assignment
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/f615ecfa4ccdda92.
Report an issue: GitHub.