📄 no-non-null-assertion¶
📊 Analysis Summary¶
| Metric | Count |
|---|---|
| 🔧 Functions | 3 |
| 📦 Imports | 7 |
| 📑 Type Aliases | 1 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/eslint-plugin/src/rules/no-non-null-assertion.ts
📤 Default Export¶
| Property | Value |
|---|---|
name |
'no-non-null-assertion' |
meta.type |
'problem' |
meta.docs.description |
'Disallow non-null assertions using the ! postfix operator' |
meta.docs.recommended |
'strict' |
meta.hasSuggestions |
true |
meta.messages.noNonNull |
'Forbidden non-null assertion.' |
meta.messages.suggestOptionalChain |
'Consider using the optional chain operator ?. instead. This operator includes runtime checks, so it is safer than ... |
meta.schema |
[] |
defaultOptions |
[] |
Entry point: create — documented under Functions.
📦 Imports¶
| Name | Source |
|---|---|
TSESLint |
@typescript-eslint/utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
createRule |
../util |
isAssignee |
../util |
isNonNullAssertionPunctuator |
../util |
nullThrows |
../util |
NullThrowsReasons |
../util |
Functions¶
create(context: any): { TSNonNullExpression(node: any): void; }¶
Parameters:
contextany
Returns: { TSNonNullExpression(node: any): void; }
Calls:
nullThrows (from ../util)context.sourceCode.getTokenAfterNullThrowsReasons.MissingTokenfixer.replaceTextfixer.removeisAssignee (from ../util)suggest.pushreplaceTokenWithOptionalfixer.insertTextBeforeremoveTokencontext.report
Internal Comments:
// it always exists in non-null assertion (x2)
// it is x![y]?.z (x4)
// it is x!.y?.z (x4)
// x!.y?.z (x2)
// ^ punctuator (x2)
// it is x!?.[y].z or x!?.y.z (x4)
// it is x.y?.z!() (x4)
// it is x.y.z!?.() (x4)
Code
create(context) {
return {
TSNonNullExpression(node): void {
const suggest: TSESLint.ReportSuggestionArray<MessageIds> = [];
// it always exists in non-null assertion
const nonNullOperator = nullThrows(
context.sourceCode.getTokenAfter(
node.expression,
isNonNullAssertionPunctuator,
),
NullThrowsReasons.MissingToken('!', 'expression'),
);
function replaceTokenWithOptional(): TSESLint.ReportFixFunction {
return fixer => fixer.replaceText(nonNullOperator, '?.');
}
function removeToken(): TSESLint.ReportFixFunction {
return fixer => fixer.remove(nonNullOperator);
}
if (
node.parent.type === AST_NODE_TYPES.MemberExpression &&
node.parent.object === node &&
!isAssignee(node.parent)
) {
if (!node.parent.optional) {
if (node.parent.computed) {
// it is x![y]?.z
suggest.push({
messageId: 'suggestOptionalChain',
fix: replaceTokenWithOptional(),
});
} else {
// it is x!.y?.z
suggest.push({
messageId: 'suggestOptionalChain',
fix(fixer) {
// x!.y?.z
// ^ punctuator
const punctuator = nullThrows(
context.sourceCode.getTokenAfter(nonNullOperator),
NullThrowsReasons.MissingToken('.', '!'),
);
return [
fixer.remove(nonNullOperator),
fixer.insertTextBefore(punctuator, '?'),
];
},
});
}
} else {
// it is x!?.[y].z or x!?.y.z
suggest.push({
messageId: 'suggestOptionalChain',
fix: removeToken(),
});
}
} else if (
node.parent.type === AST_NODE_TYPES.CallExpression &&
node.parent.callee === node
) {
if (!node.parent.optional) {
// it is x.y?.z!()
suggest.push({
messageId: 'suggestOptionalChain',
fix: replaceTokenWithOptional(),
});
} else {
// it is x.y.z!?.()
suggest.push({
messageId: 'suggestOptionalChain',
fix: removeToken(),
});
}
}
context.report({
node,
messageId: 'noNonNull',
suggest,
});
},
};
}
Internal helpers¶
Declared inside another function in this file.
replaceTokenWithOptional(): TSESLint.ReportFixFunction¶
Returns: TSESLint.ReportFixFunction
Calls:
fixer.replaceText
Code
removeToken(): TSESLint.ReportFixFunction¶
Returns: TSESLint.ReportFixFunction
Calls:
fixer.remove
Code
Type Aliases¶
MessageIds¶
Generated by Syntax Scribe