oxc-project/oxc · warning · OxcDiagnostic
Confusing combinations of non-null assertion and equal test
Error message
Confusing combinations of non-null assertion and equal test like `a! {op_str} b`, which looks very similar to not equal `a !{op_str} b`. What it means
typescript/no-confusing-non-null-assertion flags binary expressions with ==, ===, !=, !== whose left side ends in a non-null assertion `!`. When the expression ends directly in `!` at depth 0 (e.g. `a! === b`), this variant is emitted because the text looks like the negated comparison `a !== b` / `a != b` with one stray space.
Source
Thrown at crates/oxc_linter/src/rules/typescript/no_confusing_non_null_assertion.rs:58
/// a! instanceof b;
/// ```
///
/// Examples of **correct** code for this rule:
/// ```ts
/// a == b;
/// a !== b;
/// a === b;
/// ```
NoConfusingNonNullAssertion,
typescript,
suspicious,
suggestion,
version = "0.6.1",
short_description = "Disallow non-null assertion in locations that may be confusing.",
);
fn not_need_no_confusing_non_null_assertion_diagnostic(op_str: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
r"Confusing combinations of non-null assertion and equal test like `a! {op_str} b`, which looks very similar to not equal `a !{op_str} b`."
))
.with_help(r"Remove the `!`, or prefix the `=` with it.")
.with_label(span)
}
fn wrap_up_no_confusing_non_null_assertion_diagnostic(op_str: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
r"Confusing combinations of non-null assertion and equal test like `a! {op_str} b`, which looks very similar to not equal `a !{op_str} b`."
))
.with_help(
r"Wrap left-hand side in parentheses to avoid putting non-null assertion `!` and `=` together.",
)
.with_label(span)
}
fn confusing_non_null_assignment_assertion_diagnostic(op_str: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(View on GitHub (pinned to 36ec0ef2ba)
Solutions
- If you meant the comparison, remove the `!`: `a === b`
- If you meant negation, prefix the `=` with the `!`: write `a !== b` instead of `a! == b`
- If the assertion is intentional, disambiguate by wrapping: `(a!) === b`
Example fix
// before (assertion intended)
if (a! == b) {}
// after
if (a === b) {} // no assertion needed
// or, if the assertion is intentional:
if ((a!) === b) {} Defensive patterns
Strategy: type-guard
Validate before calling
// Keep the rule on in CI so visual-confusion comparisons never land:
// .oxlintrc.json
{
"rules": { "typescript/no-confusing-non-null-assertion": "warn" }
} Type guard
function isDefined<T>(v: T | null | undefined): v is T {
return v !== null && v !== undefined;
}
// instead of `a! === b`, narrow first
if (isDefined(a)) {
if (a === b) { /* ... */ }
} Prevention
- Prefer nullish checks or default values over `!` before comparisons: `a ?? fallback === b` needs parens too, so keep it simple
- Format with spaces consistently (a! vs a !) and read `!` before `=` as assertion, not negation
- Enable typescript/no-non-null-assertion in stricter codebases to remove `!` entirely
When it happens
Trigger: `a! == b`, `a! === b`, `a! != b`, `a! !== b` where the LHS is a plain TSNonNullExpression (bang_depth == 0 in get_depth_ends_in_bang); also `a!.b! === c` style chains ending in `!`.
Common situations: Developers intending `a !== b` but typing `a! == b` or vice versa; optional-heavy code where `!` assertions are habitual; typos that are syntactically valid and silently change meaning.
Related errors
- Confusing combinations of non-null assertion and assignment
- Confusing combination of non-null assertion and `{op_str}` o
- encountered allocation error
- Do not use @ts-{ts_comment_name} because it alters compilati
- Use "@ts-expect-error" instead of @ts-ignore, as "@ts-ignore
AI-assisted analysis of oxc-project/oxc@36ec0ef2ba (2026-08-20).
Data as JSON: /api/errors/f52af5a1ef54aa30.
Report an issue: GitHub.