8000 fix(eslint-plugin): [method-signature-style] fix overloaded methods t… · DudaGod/typescript-eslint@7f3fba3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7f3fba3

Browse files
authored
fix(eslint-plugin): [method-signature-style] fix overloaded methods to an intersection type (typescript-eslint#1966)
1 parent f78f13a commit 7f3fba3

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed

packages/eslint-plugin/docs/rules/method-signat 10000 ure-style.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ interface T1 {
4343
type T2 = {
4444
func(arg: boolean): void;
4545
};
46+
interface T3 {
47+
func(arg: number): void;
48+
func(arg: string): void;
49+
func(arg: boolean): void;
50+
}
4651
```
4752

4853
Examples of **correct** code with `property` option.
@@ -54,6 +59,12 @@ interface T1 {
5459
type T2 = {
5560
func: (arg: boolean) => void;
5661
};
62+
// this is equivalent to the overload
63+
interface T3 {
64+
func: ((arg: number) => void) &
65+
((arg: string) => void) &
66+
((arg: boolean) => void);
67+
}
5768
```
5869

5970
Examples of **incorrect** code with `method` option.

packages/eslint-plugin/src/rules/method-signature-style.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,56 @@ export default util.createRule<Options, MessageIds>({
103103
return;
104104
}
105105

106+
const duplicatedKeyMethodNodes: TSESTree.TSMethodSignature[] =
107+
methodNode.parent?.type === AST_NODE_TYPES.TSInterfaceBody
108+
? methodNode.parent.body.filter(
109+
(element): element is TSESTree.TSMethodSignature =>
110+
element.type === AST_NODE_TYPES.TSMethodSignature &&
111+
element !== methodNode &&
112+
getMethodKey(element) === getMethodKey(methodNode),
113+
)
114+
: [];
115+
116+
if (duplicatedKeyMethodNodes.length > 0) {
117+
context.report({
118+
node: methodNode,
119+
messageId: 'errorMethod',
120+
*fix(fixer) {
121+
const methodNodes = [
122+
methodNode,
123+
...duplicatedKeyMethodNodes,
124+
].sort((a, b) => (a.range[0] < b.range[0] ? -1 : 1));
125+
const typeString = methodNodes.reduce((str, node, idx, nodes) => {
126+
const params = getMethodParams(node);
127+
const returnType = getMethodReturnType(node);
128+
return `${str}(${params} => ${returnType})${
129+
idx !== nodes.length - 1 ? ' & ' : ''
130+
}`;
131+
}, '');
132+
const key = getMethodKey(methodNode);
133+
const delimiter = getDelimiter(methodNode);
134+
yield fixer.replaceText(
135+
methodNode,
136+
`${key}: ${typeString}${delimiter}`,
137+
);
138+
for (const node of duplicatedKeyMethodNodes) {
139+
const lastToken = sourceCode.getLastToken(node);
140+
if (lastToken) {
141+
const nextToken = sourceCode.getTokenAfter(lastToken);
142+
if (nextToken) {
143+
yield fixer.remove(node);
144+
yield fixer.replaceTextRange(
145+
[lastToken.range[1], nextToken.range[0]],
146+
'',
147+
);
148+
}
149+
}
150+
}
151+
},
152+
});
153+
return;
154+
}
155+
106156
context.report({
107157
node: methodNode,
108158
messageId: 'errorMethod',

packages/eslint-plugin/tests/rules/method-signature-style.test.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,5 +226,128 @@ interface Foo {
226226
},
227227
],
228228
},
229+
{
230+
code: noFormat`
231+
interface Foo {
232+
foo(): one;
233+
foo(): two;
234+
foo(): three;
235+
}
236+
`,
237+
output: noFormat`
238+
interface Foo {
239+
foo: (() => one) & (() => two) & (() => three);
240+
}
241+
`,
242+
errors: [
243+
{
244+
messageId: 'errorMethod',
245+
line: 3,
246+
},
247+
{
248+
messageId: 'errorMethod',
249+
line: 4,
250+
},
251+
{
252+
messageId: 'errorMethod',
253+
line: 5,
254+
},
255+
],
256+
},
257+
{
258+
code: noFormat`
259+
interface Foo {
260+
foo(bar: string): one;
261+
foo(bar: number, baz: string): two;
262+
foo(): three;
263+
}
264+
`,
265+
output: noFormat`
266+
interface Foo {
267+
foo: ((bar: string) => one) & ((bar: number, baz: string) => two) & (() => three);
268+
}
269+
`,
270+
errors: [
271+
{
272+
messageId: 'errorMethod',
273+
line: 3,
274+
},
275+
{
276+
messageId: 'errorMethod',
277+
line: 4,
278+
},
279+
{
280+
messageId: 'errorMethod',
281+
line: 5,
282+
},
283+
],
284+
},
285+
{
286+
code: noFormat`
287+
interface Foo {
288+
[foo](bar: string): one;
289+
[foo](bar: number, baz: string): two;
290+
[foo](): three;
291+
}
292+
`,
293+
output: noFormat`
294+
interface Foo {
295+
[foo]: ((bar: string) => one) & ((bar: number, baz: string) => two) & (() => three);
296+
}
297+
`,
298+
errors: [
299+
{
300+
messageId: 'errorMethod',
301+
line: 3,
302+
},
303+
{
304+
messageId: 'errorMethod',
305+
line: 4,
306+
},
307+
{
308+
messageId: 'errorMethod',
309+
line: 5,
310+
},
311+
],
312+
},
313+
{
314+
code: noFormat`
315+
interface Foo {
316+
[foo](bar: string): one;
317+
[foo](bar: number, baz: string): two;
318+
[foo](): three;
319+
bar(arg: string): void;
320+
bar(baz: number): Foo;
321+
}
322+
`,
323+
output: noFormat`
324+
interface Foo {
325+
[foo]: ((bar: string) => one) & ((bar: number, baz: string) => two) & (() => three);
326+
bar: ((arg: string) => void) & ((baz: number) => Foo);
327+
}
328+
`,
329+
errors: [
330+
{
331+
messageId: 'errorMethod',
332+
line: 3,
333+
},
334+
{
335+
messageId: 'errorMethod',
336+
line: 4,
337+
},
338+
{
339+
messageId: 'errorMethod',
340+
line: 5,
341+
},
342+
{
343+
messageId: 'errorMethod',
344+
line: 6,
345+
},
346+
{
347+
messageId: 'errorMethod',
348+
line: 7,
349+
},
350+
],
351+
},
229352
],
230353
});

0 commit comments

Comments
 (0)
0