Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ad8ea64

Browse files
authored
feat(eslint-plugin): [consistent-type-assertions] autofix angle bracket assertions to as (typescript-eslint#6641)
* Autofix angle bracket assertions to as * Include parentheses
1 parent aa537e5 commit ad8ea64

File tree

2 files changed

+122
-3
lines changed

2 files changed

+122
-3
lines changed

packages/eslint-plugin/src/rules/consistent-type-assertions.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { TSESTree } from '@typescript-eslint/utils';
1+
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
22
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
33

44
import * as util from '../util';
@@ -23,6 +23,7 @@ export default util.createRule<Options, MessageIds>({
2323
name: 'consistent-type-assertions',
2424
meta: {
2525
type: 'suggestion',
26+
fixable: 'code',
2627
docs: {
2728
description: 'Enforce consistent usage of type assertions',
2829
recommended: 'strict',
@@ -83,6 +84,28 @@ export default util.createRule<Options, MessageIds>({
8384
);
8485
}
8586

87+
function getTextWithParentheses(node: TSESTree.Node): string {
88+
// Capture parentheses before and after the node
89+
let beforeCount = 0;
90+
let afterCount = 0;
91+
92+
if (util.isParenthesized(node, sourceCode)) {
93+
const bodyOpeningParen = sourceCode.getTokenBefore(
94+
node,
95+
util.isOpeningParenToken,
96+
)!;
97+
const bodyClosingParen = sourceCode.getTokenAfter(
98+
node,
99+
util.isClosingParenToken,
100+
)!;
101+
102+
beforeCount = node.range[0] - bodyOpeningParen.range[0];
103+
afterCount = bodyClosingParen.range[1] - node.range[1];
104+
}
105+
106+
return sourceCode.getText(node, beforeCount, afterCount);
107+
}
108+
86109
function reportIncorrectAssertionType(
87110
node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression,
88111
): void {
@@ -100,6 +123,19 @@ export default util.createRule<Options, MessageIds>({
100123
messageId !== 'never'
101124
? { cast: sourceCode.getText(node.typeAnnotation) }
102125
: {},
126+
fix:
127+
messageId === 'as'
128+
? (fixer): TSESLint.RuleFix[] => [
129+
fixer.replaceText(
130+
node,
131+
getTextWithParentheses(node.expression),
132+
),
133+
fixer.insertTextAfter(
134+
node,
135+
` as ${getTextWithParentheses(node.typeAnnotation)}`,
136+
),
137+
]
138+
: undefined,
103139
});
104140
}
105141

packages/eslint-plugin/tests/rules/consistent-type-assertions.test.ts

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ const ANGLE_BRACKET_TESTS_EXCEPT_CONST_CASE = `
99
const x = <Foo>new Generic<int>();
1010
const x = <A>b;
1111
const x = <readonly number[]>[1];
12-
const x = <a | b>('string');`;
12+
const x = <a | b>('string');
13+
const x = <A>!'string';
14+
const x = <A>a + b;
15+
const x = <(A)>a + (b);
16+
const x = <Foo>(new Generic<string>());
17+
const x = (new (<Foo>Generic<string>)());`;
1318

1419
const ANGLE_BRACKET_TESTS = `${ANGLE_BRACKET_TESTS_EXCEPT_CONST_CASE}
1520
const x = <const>{ key: 'value' };
@@ -19,7 +24,12 @@ const AS_TESTS_EXCEPT_CONST_CASE = `
1924
const x = new Generic<int>() as Foo;
2025
const x = b as A;
2126
const x = [1] as readonly number[];
22-
const x = ('string') as a | b;`;
27+
const x = ('string') as a | b;
28+
const x = !'string' as A;
29+
const x = a as A + b;
30+
const x = a as (A) + (b);
31+
const x = (new Generic<string>()) as Foo;
32+
const x = (new (Generic<string> as Foo)());`;
2333

2434
const AS_TESTS = `${AS_TESTS_EXCEPT_CONST_CASE}
2535
const x = { key: 'value' } as const;
@@ -164,6 +174,26 @@ ruleTester.run('consistent-type-assertions', rule, {
164174
messageId: 'angle-bracket',
165175
line: 6,
166176
},
177+
{
178+
messageId: 'angle-bracket',
179+
line: 7,
180+
},
181+
{
182+
messageId: 'angle-bracket',
183+
line: 8,
184+
},
185+
{
186+
messageId: 'angle-bracket',
187+
line: 9,
188+
},
189+
{
190+
messageId: 'angle-bracket',
191+
line: 10,
192+
},
193+
{
194+
messageId: 'angle-bracket',
195+
line: 11,
196+
},
167197
],
168198
}),
169199
...batchedSingleLineTests({
@@ -194,7 +224,28 @@ ruleTester.run('consistent-type-assertions', rule, {
194224
messageId: 'as',
195225
line: 6,
196226
},
227+
{
228+
messageId: 'as',
229+
line: 7,
230+
},
231+
{
232+
messageId: 'as',
233+
line: 8,
234+
},
235+
{
236+
messageId: 'as',
237+
line: 9,
238+
},
239+
{
240+
messageId: 'as',
241+
line: 10,
242+
},
243+
{
244+
messageId: 'as',
245+
line: 11,
246+
},
197247
],
248+
output: AS_TESTS,
198249
}),
199250
...batchedSingleLineTests({
200251
code: AS_TESTS_EXCEPT_CONST_CASE,
@@ -224,6 +275,22 @@ ruleTester.run('consistent-type-assertions', rule, {
224275
messageId: 'never',
225276
line: 6,
226277
},
278+
{
279+
messageId: 'never',
280+
line: 7,
281+
},
282+
{
283+
messageId: 'never',
284+
line: 8,
285+
},
286+
{
287+
messageId: 'never',
288+
line: 9,
289+
},
290+
{
291+
messageId: 'never',
292+
line: 10,
293+
},
227294
],
228295
}),
229296
...batchedSingleLineTests({
@@ -254,6 +321,22 @@ ruleTester.run('consistent-type-assertions', rule, {
254321
messageId: 'never',
255322
line: 6,
256323
},
324+
{
325+
messageId: 'never',
326+
line: 7,
327+
},
328+
{
329+
messageId: 'never',
330+
line: 8,
331+
},
332+
{
333+
messageId: 'never',
334+
line: 9,
335+
},
336+
{
337+
messageId: 'never',
338+
line: 10,
339+
},
257340
],
258341
}),
259342
...batchedSingleLineTests({

0 commit comments

Comments
 (0)