diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts index f191efa2f4e7..5307c4bfd0cc 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts @@ -59,7 +59,13 @@ export default createRule({ // Quick path: if the type parameter is used multiple times in the AST, // we don't need to dip into types to know it's repeated. - if (isTypeParameterRepeatedInAST(esTypeParameter, scope.references)) { + if ( + isTypeParameterRepeatedInAST( + esTypeParameter, + scope.references, + node.body?.range[0] ?? node.returnType?.range[1], + ) + ) { continue; } @@ -86,11 +92,12 @@ export default createRule({ function isTypeParameterRepeatedInAST( node: TSESTree.TSTypeParameter, references: Reference[], + startOfBody = Infinity, ): boolean { let total = 0; for (const reference of references) { - // References inside the type parameter's definition don't count. + // References inside the type parameter's definition don't count... if ( reference.identifier.range[0] < node.range[1] && reference.identifier.range[1] > node.range[0] @@ -98,6 +105,11 @@ function isTypeParameterRepeatedInAST( continue; } + // ...nor references that are outside the declaring signature. + if (reference.identifier.range[0] > startOfBody) { + continue; + } + // Neither do references that aren't to the same type parameter, // namely value-land (non-type) identifiers of the type parameter's type, // and references to different type parameters or values. @@ -110,7 +122,9 @@ function isTypeParameterRepeatedInAST( // If the type parameter is being used as a type argument, then we // know the type parameter is being reused and can't be reported. - if (reference.identifier.parent.type === AST_NODE_TYPES.TSTypeReference) { + if ( + reference.identifier.parent.type === AST_NODE_TYPES.TSTypeReference + ) { const grandparent = skipConstituentsUpward( reference.identifier.parent.parent, ); diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-type-parameters.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-type-parameters.test.ts index e5a7558e2f49..79db12a954a3 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-type-parameters.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-type-parameters.test.ts @@ -445,6 +445,46 @@ ruleTester.run('no-unnecessary-type-parameters', rule, { { messageId: 'sole', data: { name: 'B' } }, ], }, + { + code: ` + function foo(_: T) { + const x: T = null!; + const y: T = null!; + } + `, + errors: [{ messageId: 'sole', data: { name: 'T' } }], + }, + { + code: ` + function foo(_: T): void { + const x: T = null!; + const y: T = null!; + } + `, + errors: [{ messageId: 'sole', data: { name: 'T' } }], + }, + { + code: ` + function foo(_: T): (input: T) => T { + const x: T = null!; + const y: T = null!; + } + `, + errors: [{ messageId: 'sole', data: { name: 'T' } }], + }, + { + code: ` + function foo(_: T) { + function withX(): T { + return null!; + } + function withY(): T { + return null!; + } + } + `, + errors: [{ messageId: 'sole', data: { name: 'T' } }], + }, { code: ` function parseYAML(input: string): T { 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