Skip to content

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

Merged

Conversation

kirkwaiblinger
Copy link
Member

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 with unknown instead since that's how it behaves.

@typescript-eslint
Copy link
Contributor

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.

Copy link

netlify bot commented Oct 15, 2024

Deploy Preview for typescript-eslint ready!

Name Link
🔨 Latest commit 8927800
🔍 Latest deploy log https://app.netlify.com/sites/typescript-eslint/deploys/67114edcf337350008f72edf
😎 Deploy Preview https://deploy-preview-10149--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 98 (🔴 down 1 from production)
Accessibility: 100 (no change from production)
Best Practices: 92 (no change from production)
SEO: 90 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

nx-cloud bot commented Oct 15, 2024

☁️ Nx Cloud Report

CI 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 targets

Sent with 💌 from NxCloud.

@kirkwaiblinger kirkwaiblinger marked this pull request as ready for review October 15, 2024 00:21
Copy link

codecov bot commented Oct 15, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 86.16%. Comparing base (7effdea) to head (8927800).
Report is 12 commits behind head on main.

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              
Flag Coverage Δ
unittest 86.16% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...plugin/src/rules/no-unnecessary-type-parameters.ts 92.40% <100.00%> (+0.97%) ⬆️

@kirkwaiblinger kirkwaiblinger requested a review from danvk October 15, 2024 00:41
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 🙌

Comment on lines 124 to 129
/* 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) {
Copy link
Member

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?

Suggested change
/* 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) {

Copy link
Member Author

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.

  1. ESTree selector inspects function/method:
    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');
    },
    };
  2. We switch into the ts AST node world with a type assertion:
    function checkNode(node: TSESTree.FunctionLike, descriptor: string): void {
    const tsNode = parserServices.esTreeNodeToTSNodeMap.get(
    node,
    ) as NodeWithTypeParameters;
  3. We traverse to its type parameters and back out to the ESTree type parameter node
    for (const typeParameter of tsNode.typeParameters) {
    const esTypeParameter =
    parserServices.tsNodeToESTreeNodeMap.get<TSESTree.TSTypeParameter>(
    typeParameter,
    );
  4. 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):
    const typeParams = nullThrows(
    node.typeParameters,
    'node should have type parameters',
    ).params;
  5. 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>

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i chop 🔪

@kirkwaiblinger kirkwaiblinger added the 1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge label Oct 17, 2024
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg left a 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. 🚀

@JoshuaKGoldberg JoshuaKGoldberg merged commit c8e7c27 into typescript-eslint:main Oct 21, 2024
64 checks passed
@kirkwaiblinger kirkwaiblinger deleted the nutp-suggestions branch October 21, 2024 15:05
renovate bot added a commit to mmkal/eslint-plugin-mmkal that referenced this pull request Oct 21, 2024
##### [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.
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Oct 22, 2024
| 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.
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Oct 22, 2024
| 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.
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhancement: [no-unnecessary-type-parameters] Add suggestions for simple cases.
2 participants