oxc-project/oxc · warning · OxcDiagnostic
Confusing combination of non-null assertion and `{op_str}` o
Error message
Confusing combination of non-null assertion and `{op_str}` operator like `a! {op_str} b`, which might be misinterpreted as `!(a {op_str} b)`. What it means
Operator variant of typescript/no-confusing-non-null-assertion: the left operand of `in` or `instanceof` is non-null asserted, as in `a! in obj` or `a! instanceof C`. The text can be misread as the negation `!(a in obj)`, and the precedence of `!` here is assertion, not logical not, which is the trap.
Source
Thrown at crates/oxc_linter/src/rules/typescript/no_confusing_non_null_assertion.rs:84
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!(
r"Confusing combinations of non-null assertion and assignment like `a! {op_str} b`, which looks very similar to not equal `a !{op_str} b`."
))
.with_help(r"Remove the `!`, or wrap the left-hand side in parentheses.")
.with_label(span)
}
fn confusing_non_null_operator_diagnostic(op_str: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!(
"Confusing combination of non-null assertion and `{op_str}` operator like `a! {op_str} b`, which might be misinterpreted as `!(a {op_str} b)`."
))
.with_help("Remove the `!`, or wrap the left-hand side in parentheses.")
.with_label(span)
}
fn get_depth_ends_in_bang(expr: &Expression<'_>) -> Option<u32> {
match expr {
Expression::TSNonNullExpression(_) => Some(0),
Expression::ChainExpression(chain_expr) => {
matches!(&chain_expr.expression, ChainElement::TSNonNullExpression(_)).then_some(0)
}
Expression::BinaryExpression(binary_expr) => {
get_depth_ends_in_bang(&binary_expr.right).map(|x| x + 1)
}
Expression::UnaryExpression(unary_expr) => {
get_depth_ends_in_bang(&unary_expr.argument).map(|x| x + 1)
}View on GitHub (pinned to 36ec0ef2ba)
Solutions
- Remove the `!` if the operand cannot be null/undefined: `key in cache`
- If you meant logical negation, write it explicitly: `!(key in cache)`
- If the assertion is intentional, wrap the operand: `(key!) in cache`
Example fix
// before
if (key! in cache) {}
// after
if (key in cache) {}
// or, if negation was intended:
if (!(key in cache)) {} Defensive patterns
Strategy: type-guard
Validate before calling
// .oxlintrc.json
{
"rules": { "typescript/no-confusing-non-null-assertion": "warn" }
} Type guard
function isNonEmptyString(v: string | null | undefined): v is string {
return typeof v === 'string' && v.length > 0;
}
// instead of `key! in cache`, narrow or drop the assertion
if (isNonEmptyString(key) && key in cache) { /* ... */ }
// negation must be written explicitly:
if (!(key in cache)) { /* ... */ } Prevention
- Never write `!` directly before `in` or `instanceof`; read it as logical-not and double-check intent
- Keep candidate keys typed as non-nullable so the assertion is unnecessary
- Use Set.has / Map.has for membership tests where `in` on objects invites this pattern
When it happens
Trigger: Any BinaryExpression with operator `in` or `instanceof` whose left side ends in `!`, e.g. `key! in cache`, `err! instanceof TypeError`; the run() special-cases these two operators separately from the equality variants.
Common situations: Type-guard-style code checking keys or error types after an assertion; developers intending `!(a in obj)` but writing `a! in obj`; ported JS code that used `!` as logical not before these operators.
Related errors
- Confusing combinations of non-null assertion and equal test
- Confusing combinations of non-null assertion and assignment
- 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/252677f4fc7afe7e.
Report an issue: GitHub.