Skip to content

fix(eslint-plugin): [no-unnecessary-type-assertion] detect unnecessary non-null-assertion on a call expression #8143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ export default createRule<Options, MessageId>({
function checkCallExpression(node: TSESTree.CallExpression): void {
// If this is something like arr.filter(x => /*condition*/), check `condition`
if (isArrayPredicateFunction(node) && node.arguments.length) {
const callback = node.arguments[0]!;
const callback = node.arguments[0];
// Inline defined functions
if (
callback.type === AST_NODE_TYPES.ArrowFunctionExpression ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,18 @@ export default createRule<Options, MessageIds>({
const type = getConstrainedTypeAtLocation(services, node.expression);

if (!isNullableType(type)) {
if (isPossiblyUsedBeforeAssigned(node.expression)) {
if (
node.expression.type === AST_NODE_TYPES.Identifier &&
isPossiblyUsedBeforeAssigned(node.expression)
) {
return;
}

context.report({
node,
messageId: 'unnecessaryAssertion',
fix(fixer) {
return fixer.removeRange([
node.expression.range[1],
node.range[1],
]);
return fixer.removeRange([node.range[1] - 1, node.range[1]]);
},
});
} else {
Expand Down Expand Up @@ -274,7 +274,10 @@ export default createRule<Options, MessageIds>({
: null;
}
return fixer.removeRange([
node.expression.range[1] + 1,
node.expression.range[1] +
(node.expression.type === AST_NODE_TYPES.CallExpression
? 0
: 1),
node.range[1],
]);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,30 @@ let values: number[] = [];

value = values.pop()!;
`,
`
declare function foo(): number | undefined;
const a = foo()!;
`,
`
declare function foo(): number | undefined;
const a = foo() as number;
`,
`
declare function foo(): number | undefined;
const a = <number>foo();
`,
`
declare const arr: (object | undefined)[];
const item = arr[0]!;
`,
`
declare const arr: (object | undefined)[];
const item = arr[0] as object;
`,
`
declare const arr: (object | undefined)[];
const item = <object>arr[0];
`,
],

invalid: [
Expand Down Expand Up @@ -518,5 +542,118 @@ y = 0;
},
],
},
{
code: `
declare function foo(): number;
const a = foo()!;
`,
output: `
declare function foo(): number;
const a = foo();
`,
errors: [
{
messageId: 'unnecessaryAssertion',
line: 3,
column: 11,
endColumn: 17,
},
],
},
{
code: `
const b = new Date()!;
`,
output: `
const b = new Date();
`,
errors: [
{
messageId: 'unnecessaryAssertion',
line: 2,
},
],
},
{
code: `
const b = (1 + 1)!;
`,
output: `
const b = (1 + 1);
`,
errors: [
{
messageId: 'unnecessaryAssertion',
line: 2,
column: 11,
endColumn: 19,
},
],
},
{
code: `
declare function foo(): number;
const a = foo() as number;
`,
output: `
declare function foo(): number;
const a = foo();
`,
errors: [
{
messageId: 'unnecessaryAssertion',
line: 3,
column: 11,
},
],
},
{
code: `
declare function foo(): number;
const a = <number>foo();
`,
output: `
declare function foo(): number;
const a = foo();
`,
errors: [
{
messageId: 'unnecessaryAssertion',
line: 3,
},
],
},
{
code: `
type RT = { log: () => void };
declare function foo(): RT;
(foo() as RT).log;
`,
output: `
type RT = { log: () => void };
declare function foo(): RT;
(foo()).log;
`,
errors: [
{
messageId: 'unnecessaryAssertion',
},
],
},
{
code: `
declare const arr: object[];
const item = arr[0]!;
`,
output: `
declare const arr: object[];
const item = arr[0];
`,
errors: [
{
messageId: 'unnecessaryAssertion',
},
],
},
],
});