-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat(eslint-plugin): [no-unnecessary-type-parameters] add suggestion fixer #10149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(eslint-plugin): [no-unnecessary-type-parameters] add suggestion fixer #10149
Conversation
Thanks for the PR, @kirkwaiblinger! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. |
✅ Deploy Preview for typescript-eslint ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
☁️ Nx Cloud ReportCI is running/has finished running commands for commit 8927800. As they complete they will appear below. Click to see the status, the terminal output, and the build insights. 📂 See all runs for this CI Pipeline Execution ✅ Successfully ran 2 targetsSent with 💌 from NxCloud. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #10149 +/- ##
==========================================
+ Coverage 86.15% 86.16% +0.01%
==========================================
Files 429 429
Lines 15005 15023 +18
Branches 4353 4357 +4
==========================================
+ Hits 12927 12945 +18
Misses 1729 1729
Partials 349 349
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! 🙌
/* istanbul ignore if: this is an assertion that should never happen */ | ||
if (index === -1) { | ||
throw new Error( | ||
"type parameter should be in node's type parameters", | ||
); | ||
} else if (typeParams.length === 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why include this, if it's not something that can even be unit tested?
/* istanbul ignore if: this is an assertion that should never happen */ | |
if (index === -1) { | |
throw new Error( | |
"type parameter should be in node's type parameters", | |
); | |
} else if (typeParams.length === 1) { | |
if (typeParams.length === 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My paranoia is: the rule fixer assumes the type parameter to be removed/replaced is in the method/function/class's declared list of type parameters of the node being inspected. But the way we get the type parameter to be removed is indirect.
- ESTree selector inspects function/method:
typescript-eslint/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts
Lines 206 to 226 in 9a42740
return { [[ 'ArrowFunctionExpression[typeParameters]', 'FunctionDeclaration[typeParameters]', 'FunctionExpression[typeParameters]', 'TSCallSignatureDeclaration[typeParameters]', 'TSConstructorType[typeParameters]', 'TSDeclareFunction[typeParameters]', 'TSEmptyBodyFunctionExpression[typeParameters]', 'TSFunctionType[typeParameters]', 'TSMethodSignature[typeParameters]', ].join(', ')](node: TSESTree.FunctionLike): void { checkNode(node, 'function'); }, [[ 'ClassDeclaration[typeParameters]', 'ClassExpression[typeParameters]', ].join(', ')](node: TSESTree.FunctionLike): void { checkNode(node, 'class'); }, }; - We switch into the ts AST node world with a type assertion:
typescript-eslint/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts
Lines 43 to 46 in 9a42740
function checkNode(node: TSESTree.FunctionLike, descriptor: string): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get( node, ) as NodeWithTypeParameters; - We traverse to its type parameters and back out to the ESTree type parameter node
typescript-eslint/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts
Lines 54 to 58 in 9a42740
for (const typeParameter of tsNode.typeParameters) { const esTypeParameter = parserServices.tsNodeToESTreeNodeMap.get<TSESTree.TSTypeParameter>( typeParameter, ); - We assume that the ESTree node from step 1. is the grandparent of the type parameter from 3, in order to get its type parameter declaration (which we have to assert even exists):
typescript-eslint/packages/eslint-plugin/src/rules/no-unnecessary-type-parameters.ts
Lines 117 to 120 in 9a42740
const typeParams = nullThrows( node.typeParameters, 'node should have type parameters', ).params; - We need to figure out what position the reported ESTree type parameter is within that asserted-to-exist type parameter declaration's list of type parameters. My goal was to double-check here that the reported type parameter really is in that list, since, we have come here by two different paths completely, and it doesn't seem that far-fetched that a change to the rule logic could break some of our assumptions.
For reference, the ASTs look like
ESTREE: node that we inspect ---(maybe has) ---> TSTypeParameterDeclaration -----> Array<TypeParameter>
TS AST: node that we inspect -----> Array<TypeParameterDeclaration>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyways, I can go ahead and remove it if you prefer. Just one of those things that I prefer to do so that we fail faster and more understandably when a nonlocal code change breaks some of our assumptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this kind of strategy used to be a lot more common in the project. But it practically never paid off 😞. Our test coverage is so high & users are so active in reporting that it just ended up being a lot of code bloat. I'm still a -1 on it, but if you want to advocate for it I wouldn't be opposed to hearing more inputs from the team.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i chop 🔪
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this only adds to the linting side of things, rather than changing functionality, I say let's merge for today's release. 🚀
##### [v8.11.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8110-2024-10-21) ##### 🚀 Features - **eslint-plugin:** \[no-unnecessary-type-parameters] add suggestion fixer ([#10149](typescript-eslint/typescript-eslint#10149)) - **eslint-plugin:** \[no-base-to-string] add support for catching toLocaleString ([#10138](typescript-eslint/typescript-eslint#10138)) ##### 🩹 Fixes - **eslint-plugin:** \[class-literal-property-style] don't report nodes with `override` keyword ([#10135](typescript-eslint/typescript-eslint#10135)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - Yukihiro Hasegawa [@y-hsgw](https://github.com/y-hsgw) You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.10.0 | 8.11.0 | | npm | @typescript-eslint/parser | 8.10.0 | 8.11.0 | ## [v8.11.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8110-2024-10-21) ##### 🚀 Features - **eslint-plugin:** \[no-unnecessary-type-parameters] add suggestion fixer ([#10149](typescript-eslint/typescript-eslint#10149)) - **eslint-plugin:** \[no-base-to-string] add support for catching toLocaleString ([#10138](typescript-eslint/typescript-eslint#10138)) ##### 🩹 Fixes - **eslint-plugin:** \[class-literal-property-style] don't report nodes with `override` keyword ([#10135](typescript-eslint/typescript-eslint#10135)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - Yukihiro Hasegawa [@y-hsgw](https://github.com/y-hsgw) You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.10.0 | 8.11.0 | | npm | @typescript-eslint/parser | 8.10.0 | 8.11.0 | ## [v8.11.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8110-2024-10-21) ##### 🚀 Features - **eslint-plugin:** \[no-unnecessary-type-parameters] add suggestion fixer ([#10149](typescript-eslint/typescript-eslint#10149)) - **eslint-plugin:** \[no-base-to-string] add support for catching toLocaleString ([#10138](typescript-eslint/typescript-eslint#10138)) ##### 🩹 Fixes - **eslint-plugin:** \[class-literal-property-style] don't report nodes with `override` keyword ([#10135](typescript-eslint/typescript-eslint#10135)) ##### ❤️ Thank You - Kirk Waiblinger [@kirkwaiblinger](https://github.com/kirkwaiblinger) - Yukihiro Hasegawa [@y-hsgw](https://github.com/y-hsgw) You can read about our [versioning strategy](https://main--typescript-eslint.netlify.app/users/versioning) and [releases](https://main--typescript-eslint.netlify.app/users/releases) on our website.
PR Checklist
Overview
Offers to replace the unnecessary type parameter with its constraint (and remove the type parameter declaration).
Special case is that
T extends any
gets replaced withunknown
instead since that's how it behaves.