{"record":{"id":"d14e3149c6eeff87","repo":"oxc-project/oxc","slug":"forbidden-non-null-assertion","errorCode":null,"errorMessage":"Forbidden non-null assertion.","messagePattern":"Forbidden non-null assertion\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/typescript/no_non_null_assertion.rs","lineNumber":48,"sourceCode":"    /// x.y!;\n    /// ```\n    ///\n    /// Examples of **correct** code for this rule:\n    /// ```ts\n    /// x;\n    /// x?.y;\n    /// x.y;\n    /// ```\n    NoNonNullAssertion,\n    typescript,\n    restriction,\n    pending,\n    version = \"0.5.0\",\n    short_description = \"Disallow non-null assertions using the `!` postfix operator.\",\n);\n\nfn no_non_null_assertion_diagnostic(span: Span, is_member_expression: bool) -> OxcDiagnostic {\n    let diagnostic = OxcDiagnostic::warn(\"Forbidden non-null assertion.\")\n        .with_note(\n            \"The non-null assertion operator (`!`) removes `null` and `undefined` from the type. For example, it changes `number | undefined` to `number`.\",\n        )\n        .with_label(span);\n\n    if is_member_expression {\n        diagnostic.with_help(\"Consider using the optional chain operator `?.` instead. `x!.y` is equivalent to `x.y` at runtime and will throw if `x` is `null` or `undefined`, but `x?.y` will return `undefined`.\")\n    } else {\n        diagnostic\n    }\n}\n\nimpl Rule for NoNonNullAssertion {\n    fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {\n        let AstKind::TSNonNullExpression(expr) = node.kind() else { return };\n        let is_member_expression = ctx.nodes().parent_kind(node.id()).is_member_expression_kind();\n        ctx.diagnostic(no_non_null_assertion_diagnostic(expr.span, is_member_expression));\n    }","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/typescript/no_non_null_assertion.rs#L30-L66","documentation":"Oxlint's no-non-null-assertion bans the postfix `!` operator outright; it is a restriction rule still marked pending in the declare_oxc_lint block at no_non_null_assertion.rs:41-47. The note explains that `!` removes null and undefined from the type, and when the asserted expression feeds a member access the help at lines 53-56 recommends `?.` instead, spelling out the runtime difference.","triggerScenarios":"Any `expr!`: `foo!.bar`, `users.find(u => u.id === id)!`, `value!.toString()` - the rule flags every occurrence of the operator.","commonSituations":"Teams that adopted a zero-assertion policy; code against APIs returning `T | undefined` where developers assert instead of narrowing; adoption of this rule in an existing codebase produces a burst of these.","solutions":["Narrow explicitly: check for undefined and throw or return early","Use optional chaining `?.` and a nullish default `??`","Write a type-guard function (for example isDefined) and rely on narrowing","Fix the source API to return `T` when absence is impossible","Last resort: `// oxlint-disable-next-line typescript/no-non-null-assertion`"],"exampleFix":"// before\nconst user = users.find(u => u.id === id)!;\n\n// after\nconst user = users.find(u => u.id === id);\nif (!user) throw new Error(`user ${id} not found`);","handlingStrategy":"validation","validationCode":"npx oxlint --deny-warnings .","typeGuard":"function isDefined<T>(value: T | null | undefined): value is T {\n  return value !== null && value !== undefined;\n}\n\n// usage instead of `users.find(u => u.id === id)!`\nconst found = users.find(u => u.id === id);\nif (!isDefined(found)) throw new Error('user not found');","tryCatchPattern":null,"preventionTips":["Enable strictNullChecks and fix the source types instead of asserting at call sites","Reach for `?.`, `??`, or an isDefined guard before ever typing `!`","Track the repo's remaining `!` count (rg '!' on TS files) and drive it to zero","Grep new diffs for postfix `!` in review"],"tags":["typescript","lint","non-null-assertion","null-safety"],"backgroundTag":"non-null-assertion","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}