Skip to content

feat(eslint-plugin): [no-unnecessary-condition] add checkTypePredicates #10009

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

Conversation

kirkwaiblinger
Copy link
Member

@kirkwaiblinger kirkwaiblinger commented Sep 18, 2024

PR Checklist

Overview

  • Basically completely rewrite the existing method findAssertedArgument in SBE to use checker.getResolvedSignature() and checker.getTypePredicateOfSignature(), and move it into shared location
  • Put new behavior behind option "checkTypePredicates" - see this discord conversation for the thought process on naming
  • Add docs
  • Enable internally and suppress violations

@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 Sep 18, 2024

Deploy Preview for typescript-eslint ready!

Name Link
🔨 Latest commit 42caf70
🔍 Latest deploy log https://app.netlify.com/sites/typescript-eslint/deploys/66f204213e781c00082a7779
😎 Deploy Preview https://deploy-preview-10009--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.

@kirkwaiblinger kirkwaiblinger changed the title [no-unnecessary-condition]: add checkTruthinessAssertions feat(eslint-plugin): [no-unnecessary-condition]: add checkTruthinessAssertions Sep 18, 2024
Copy link

nx-cloud bot commented Sep 18, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit 42caf70. 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 changed the title feat(eslint-plugin): [no-unnecessary-condition]: add checkTruthinessAssertions feat(eslint-plugin): [no-unnecessary-condition] add checkTruthinessAssertions Sep 18, 2024
Copy link

codecov bot commented Sep 18, 2024

Codecov Report

Attention: Patch coverage is 93.44262% with 4 lines in your changes missing coverage. Please review.

Project coverage is 88.72%. Comparing base (1c183ab) to head (42caf70).
Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
...s/eslint-plugin/src/util/assertionFunctionUtils.ts 91.11% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #10009      +/-   ##
==========================================
+ Coverage   88.70%   88.72%   +0.01%     
==========================================
  Files         426      427       +1     
  Lines       14835    14896      +61     
  Branches     4312     4329      +17     
==========================================
+ Hits        13159    13216      +57     
- Misses       1533     1538       +5     
+ Partials      143      142       -1     
Flag Coverage Δ
unittest 88.72% <93.44%> (+0.01%) ⬆️

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

Files with missing lines Coverage Δ
...slint-plugin/src/rules/no-unnecessary-condition.ts 99.54% <100.00%> (+0.02%) ⬆️
...s/eslint-plugin/src/rules/prefer-optional-chain.ts 100.00% <ø> (ø)
...plugin/src/rules/prefer-string-starts-ends-with.ts 98.47% <100.00%> (-0.01%) ⬇️
...int-plugin/src/rules/strict-boolean-expressions.ts 100.00% <100.00%> (ø)
packages/type-utils/src/getTypeName.ts 100.00% <100.00%> (ø)
...s/eslint-plugin/src/util/assertionFunctionUtils.ts 91.11% <91.11%> (ø)

... and 10 files with indirect coverage changes

@kirkwaiblinger kirkwaiblinger marked this pull request as ready for review September 18, 2024 04:23
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.

Seems very reasonable to me! The comments were quite helpful, thanks for that. 🙌

Requesting changes on added test coverage.

Copy link
Member Author

Choose a reason for hiding this comment

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

FYI - I realized while working on this that we can use checker.getTypePredicateOfSignature(signature), which.... does all the heavy lifting for us 🤦‍♂️

So this is now much simpler. 🥳

Copy link
Member Author

Choose a reason for hiding this comment

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

See 4ac6765 for just the diff of the algorithm change

@@ -516,29 +516,6 @@ declare const nullableString: string | null;
assert(3 as any, nullableString);
`,
},
// Intentional TS error - A rest parameter must be last in a parameter list.
Copy link
Member Author

@kirkwaiblinger kirkwaiblinger Sep 21, 2024

Choose a reason for hiding this comment

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

These tests were for coverage reasons that no longer make sense with the new algorithm.
None of them crashes. 2 of them now do report, but they match how TS thinks about the situation, so it's not really a false report 🤷‍♂️

@kirkwaiblinger kirkwaiblinger added the DO NOT MERGE PRs which should not be merged yet label Sep 21, 2024
@kirkwaiblinger
Copy link
Member Author

Per discord conversation, we'll want to bring #10007 into this in order to put it behind the same option. Marking as draft until then

@kirkwaiblinger kirkwaiblinger marked this pull request as draft September 21, 2024 16:27
@kirkwaiblinger kirkwaiblinger changed the title feat(eslint-plugin): [no-unnecessary-condition] add checkTruthinessAssertions feat(eslint-plugin): [no-unnecessary-condition] add checkTypePredicates Sep 23, 2024
@kirkwaiblinger kirkwaiblinger removed the DO NOT MERGE PRs which should not be merged yet label Sep 23, 2024
@kirkwaiblinger
Copy link
Member Author

This has changed a lot since its initial version. I would recommend reviewing it more or less from scratch

@kirkwaiblinger kirkwaiblinger marked this pull request as ready for review September 23, 2024 05:22
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.

LGTM, very nice refactor!

Just one nit suggestion on test-utils.ts, otherwise 🚀 from me.

@@ -139,6 +140,7 @@ export function omitDeep(
value.push(visit(el, node));
}
node[prop] = value;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- I don't know if it's safe to change this.
Copy link
Member

Choose a reason for hiding this comment

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

Seems odd to me to leave an "I don't know if ..." in code. I tried removing them locally and some semanticInfo.test.ts snapshots broke. I got around it by:

  • Changing the type of oNode and the return types of function visit & function omitDeep to UnknownObject | undefined
  • Removing this if (isObjectLike(child)) { from the else

WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, well I'm scared of that since the one usage of omitDeep is asserted to be not null

/**
* Returns a raw copy of the typescript AST
* @param ast the AST object
* @returns copy of the AST object
*/
export function deeplyCopy<T extends NonNullable<unknown>>(ast: T): T {
return omitDeep(ast) as T;
}

But I'm realizing now that this is "just" test code so I feel a little less scared of messing around with it

Copy link
Member Author

Choose a reason for hiding this comment

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

An easier fix for now seems like just turning isObjectLike into an ordinary boolean-returning function, since its type predicate isn't actually needed in the two places it's used. 🤷 Plus, no runtime changes, yay!

Copy link
Member

Choose a reason for hiding this comment

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

🤝 perfect!

@JoshuaKGoldberg JoshuaKGoldberg added the 1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge label Sep 23, 2024
@JoshuaKGoldberg JoshuaKGoldberg merged commit a916ff2 into typescript-eslint:main Sep 29, 2024
62 checks passed
@kirkwaiblinger kirkwaiblinger deleted the no-unnecessary-condition-assertion-functions branch September 29, 2024 22:53
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 7, 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 enhancement New feature or request
Projects
None yet
2 participants