diff --git a/packages/eslint-plugin/src/rules/unified-signatures.ts b/packages/eslint-plugin/src/rules/unified-signatures.ts index c58e33085721..809b19dd1aa6 100644 --- a/packages/eslint-plugin/src/rules/unified-signatures.ts +++ b/packages/eslint-plugin/src/rules/unified-signatures.ts @@ -264,6 +264,14 @@ export default createRule({ types1: readonly TSESTree.Parameter[], types2: readonly TSESTree.Parameter[], ): Unify | undefined { + const firstParam1 = types1[0]; + const firstParam2 = types2[0]; + + // exempt signatures with `this: void` from the rule + if (isThisVoidParam(firstParam1) || isThisVoidParam(firstParam2)) { + return undefined; + } + const index = getIndexOfFirstDifference( types1, types2, @@ -294,6 +302,22 @@ export default createRule({ : undefined; } + function isThisParam(param: TSESTree.Parameter | undefined): boolean { + return ( + param != null && + param.type === AST_NODE_TYPES.Identifier && + param.name === 'this' + ); + } + + function isThisVoidParam(param: TSESTree.Parameter | undefined) { + return ( + isThisParam(param) && + (param as TSESTree.Identifier).typeAnnotation?.typeAnnotation.type === + AST_NODE_TYPES.TSVoidKeyword + ); + } + /** * Detect `a(): void` and `a(x: number): void`. * Returns the parameter declaration (`x: number` in this example) that should be optional/rest, and overload it's a part of. @@ -310,6 +334,19 @@ export default createRule({ const shorter = sig1.length < sig2.length ? sig1 : sig2; const shorterSig = sig1.length < sig2.length ? a : b; + const firstParam1 = sig1.at(0); + const firstParam2 = sig2.at(0); + // If one signature has explicit this type and another doesn't, they can't + // be unified. + if (isThisParam(firstParam1) !== isThisParam(firstParam2)) { + return undefined; + } + + // exempt signatures with `this: void` from the rule + if (isThisVoidParam(firstParam1) || isThisVoidParam(firstParam2)) { + return undefined; + } + // If one is has 2+ parameters more than the other, they must all be optional/rest. // Differ by optional parameters: f() and f(x), f() and f(x, ?y, ...z) // Not allowed: f() and f(x, y) diff --git a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts index dd8412b53ef7..30952ddebb0f 100644 --- a/packages/eslint-plugin/tests/rules/unified-signatures.test.ts +++ b/packages/eslint-plugin/tests/rules/unified-signatures.test.ts @@ -380,6 +380,21 @@ declare function f(x: boolean): unknown; `, options: [{ ignoreOverloadsWithDifferentJSDoc: true }], }, + ` +function f(): void; +function f(this: {}): void; +function f(this: void | {}): void {} + `, + ` +function f(a: boolean): void; +function f(this: {}, a: boolean): void; +function f(this: void | {}, a: boolean): void {} + `, + ` +function f(this: void, a: boolean): void; +function f(this: {}, a: boolean): void; +function f(this: void | {}, a: boolean): void {} + `, ], invalid: [ { @@ -1136,5 +1151,73 @@ declare function f(x: boolean): unknown; ], options: [{ ignoreOverloadsWithDifferentJSDoc: true }], }, + { + code: ` +function f(this: {}, a: boolean): void; +function f(this: {}, a: string): void; +function f(this: {}, a: boolean | string): void {} + `, + errors: [ + { + column: 22, + line: 3, + messageId: 'singleParameterDifference', + }, + ], + }, + { + code: ` +function f(this: {}): void; +function f(this: {}, a: string): void; +function f(this: {}, a?: string): void {} + `, + errors: [ + { + column: 22, + line: 3, + messageId: 'omittingSingleParameter', + }, + ], + }, + { + code: ` +function f(this: string): void; +function f(this: number): void; +function f(this: string | number): void {} + `, + errors: [ + { + column: 12, + data: { + failureStringStart: + 'These overloads can be combined into one signature', + type1: 'string', + type2: 'number', + }, + line: 3, + messageId: 'singleParameterDifference', + }, + ], + }, + { + code: ` +function f(this: string, a: boolean): void; +function f(this: number, a: boolean): void; +function f(this: string | number, a: boolean): void {} + `, + errors: [ + { + column: 12, + data: { + failureStringStart: + 'These overloads can be combined into one signature', + type1: 'string', + type2: 'number', + }, + line: 3, + messageId: 'singleParameterDifference', + }, + ], + }, ], }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy