Skip to content

Commit 5a56708

Browse files
authored
fix(eslint-plugin): [no-unnecessary-type-assertion] detect unnecessary non-null-assertion on a call expression (#8143)
* feat(eslint-plugin): [no-unnecessary-type-assertion] add `Identifier` check * feat(eslint-plugin): [no-unnecessary-type-assertion] update fixer for `CallExpression` * feat(eslint-plugin): [no-unnecessary-type-assertion] add test case * feat(eslint-plugin): [no-unnecessary-type-assertion] fit more cases * feat(eslint-plugin): [no-unnecessary-type-assertion] add valid test cases * fix: fix a gap and add tests * fix: typo
1 parent e80d54e commit 5a56708

File tree

3 files changed

+147
-7
lines changed

3 files changed

+147
-7
lines changed

packages/eslint-plugin/src/rules/no-unnecessary-condition.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ export default createRule<Options, MessageId>({
436436
function checkCallExpression(node: TSESTree.CallExpression): void {
437437
// If this is something like arr.filter(x => /*condition*/), check `condition`
438438
if (isArrayPredicateFunction(node) && node.arguments.length) {
439-
const callback = node.arguments[0]!;
439+
const callback = node.arguments[0];
440440
// Inline defined functions
441441
if (
442442
callback.type === AST_NODE_TYPES.ArrowFunctionExpression ||

packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -169,18 +169,18 @@ export default createRule<Options, MessageIds>({
169169
const type = getConstrainedTypeAtLocation(services, node.expression);
170170

171171
if (!isNullableType(type)) {
172-
if (isPossiblyUsedBeforeAssigned(node.expression)) {
172+
if (
173+
node.expression.type === AST_NODE_TYPES.Identifier &&
174+
isPossiblyUsedBeforeAssigned(node.expression)
175+
) {
173176
return;
174177
}
175178

176179
context.report({
177180
node,
178181
messageId: 'unnecessaryAssertion',
179182
fix(fixer) {
180-
return fixer.removeRange([
181-
node.expression.range[1],
182-
node.range[1],
183-
]);
183+
return fixer.removeRange([node.range[1] - 1, node.range[1]]);
184184
},
185185
});
186186
} else {
@@ -274,7 +274,10 @@ export default createRule<Options, MessageIds>({
274274
: null;
275275
}
276276
return fixer.removeRange([
277-
node.expression.range[1] + 1,
277+
node.expression.range[1] +
278+
(node.expression.type === AST_NODE_TYPES.CallExpression
279+
? 0
280+
: 1),
278281
node.range[1],
279282
]);
280283
},

packages/eslint-plugin/tests/rules/no-unnecessary-type-assertion.test.ts

+137
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,30 @@ let values: number[] = [];
213213
214214
value = values.pop()!;
215215
`,
216+
`
217+
declare function foo(): number | undefined;
218+
const a = foo()!;
219+
`,
220+
`
221+
declare function foo(): number | undefined;
222+
const a = foo() as number;
223+
`,
224+
`
225+
declare function foo(): number | undefined;
226+
const a = <number>foo();
227+
`,
228+
`
229+
declare const arr: (object | undefined)[];
230+
const item = arr[0]!;
231+
`,
232+
`
233+
declare const arr: (object | undefined)[];
234+
const item = arr[0] as object;
235+
`,
236+
`
237+
declare const arr: (object | undefined)[];
238+
const item = <object>arr[0];
239+
`,
216240
],
217241

218242
invalid: [
@@ -518,5 +542,118 @@ y = 0;
518542
},
519543
],
520544
},
545+
{
546+
code: `
547+
declare function foo(): number;
548+
const a = foo()!;
549+
`,
550+
output: `
551+
declare function foo(): number;
552+
const a = foo();
553+
`,
554+
errors: [
555+
{
556+
messageId: 'unnecessaryAssertion',
557+
line: 3,
558+
column: 11,
559+
endColumn: 17,
560+
},
561+
],
562+
},
563+
{
564+
code: `
565+
const b = new Date()!;
566+
`,
567+
output: `
568+
const b = new Date();
569+
`,
570+
errors: [
571+
{
572+
messageId: 'unnecessaryAssertion',
573+
line: 2,
574+
},
575+
],
576+
},
577+
{
578+
code: `
579+
const b = (1 + 1)!;
580+
`,
581+
output: `
582+
const b = (1 + 1);
583+
`,
584+
errors: [
585+
{
586+
messageId: 'unnecessaryAssertion',
587+
line: 2,
588+
column: 11,
589+
endColumn: 19,
590+
},
591+
],
592+
},
593+
{
594+
code: `
595+
declare function foo(): number;
596+
const a = foo() as number;
597+
`,
598+
output: `
599+
declare function foo(): number;
600+
const a = foo();
601+
`,
602+
errors: [
603+
{
604+
messageId: 'unnecessaryAssertion',
605+
line: 3,
606+
column: 11,
607+
},
608+
],
609+
},
610+
{
611+
code: `
612+
declare function foo(): number;
613+
const a = <number>foo();
614+
`,
615+
output: `
616+
declare function foo(): number;
617+
const a = foo();
618+
`,
619+
errors: [
620+
{
621+
messageId: 'unnecessaryAssertion',
622+
line: 3,
623+
},
624+
],
625+
},
626+
{
627+
code: `
628+
type RT = { log: () => void };
629+
declare function foo(): RT;
630+
(foo() as RT).log;
631+
`,
632+
output: `
633+
type RT = { log: () => void };
634+
declare function foo(): RT;
635+
(foo()).log;
636+
`,
637+
errors: [
638+
{
639+
messageId: 'unnecessaryAssertion',
640+
},
641+
],
642+
},
643+
{
644+
code: `
645+
declare const arr: object[];
646+
const item = arr[0]!;
647+
`,
648+
output: `
649+
declare const arr: object[];
650+
const item = arr[0];
651+
`,
652+
errors: [
653+
{
654+
messageId: 'unnecessaryAssertion',
655+
},
656+
],
657+
},
521658
],
522659
});

0 commit comments

Comments
 (0)