Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Rule proposal: Preferring .find(...) over .filter(...)[0] #6886

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

Closed
6 tasks done
JoshuaKGoldberg opened this issue Apr 11, 2023 · 13 comments · Fixed by #8216
Closed
6 tasks done

Rule proposal: Preferring .find(...) over .filter(...)[0] #6886

JoshuaKGoldberg opened this issue Apr 11, 2023 · 13 comments · Fixed by #8216
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: new plugin rule New rule request for eslint-plugin package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@JoshuaKGoldberg
Copy link
Member

Before You File a Proposal Please Confirm You Have Done The Following...

My proposal is suitable for this project

  • My proposal specifically checks TypeScript syntax, or it proposes a check that requires type information to be accurate.
  • My proposal is not a "formatting rule"; meaning it does not just enforce how code is formatted (whitespace, brace placement, etc).
  • I believe my proposal would be useful to the broader TypeScript community (meaning it is not a niche proposal).

Description

I've seen occasional code authors write code with a .filter returning element [0], perhaps not knowing that .find does the same thing. Perhaps we could write a rule that flags for this, and uses the type system to know whether the collection being .filtered is an array/array-like?

Fail Cases

const values = ['a', 'b ', 'c'];

const result = values.filter(value => value.includes(' '))[0];

Pass Cases

const values = ['a', 'b ', 'c'];

const result = values.find(value => value.includes(' '));

Additional Info

No response

@JoshuaKGoldberg JoshuaKGoldberg added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for team members to take a look enhancement: new plugin rule New rule request for eslint-plugin labels Apr 11, 2023
@armano2
Copy link
Collaborator

armano2 commented Apr 11, 2023

My proposal specifically checks TypeScript syntax, or it proposes a check that requires type information to be accurate.

https://github.com/WebbyLab/eslint-plugin-more/blob/master/docs/no-filter-instead-of-find.md

@JoshuaKGoldberg
Copy link
Member Author

JoshuaKGoldberg commented Apr 11, 2023

Why this needs the type checker:

interface JerkCode<T> {
  filter(predicate: (item: T) => boolean): JerkCode<T>;
}

declare const jerkCode: JerkCode<string>;

jerkCode.filter(item => item === "aha");

(making this explicit in case future folks ask)

@jfmengels
Copy link

I guess there should ideally also be a check to see if the filter function does a side-effect, in which case the change will affect the current behavior.

@bradzacher
Copy link
Member

bradzacher commented Apr 12, 2023

I guess there should ideally also be a check to see if the filter function does a side-effect

We can do that once we solve the halting problem 😄.
As long as it's not autofixing the code then reporting on that sort of code isn't bad.
Though TBH a side-effect in a .filter is filthy code and I want to break it to teach that person a lesson.

@jfmengels
Copy link

We can do that once we solve the halting problem 😄.

Good luck, I'm looking forward to the results 😄

Though TBH a side-effect in a .filter is filthy code and I want to break it to teach that person a lesson.

I agree it is bad because it is unexpected. But I don't know about actively wanting to break it 😅
I do agree that not having an autofix would solve the problem. A suggestion would be possible (with a warning about side-effects ideally?), but autofix would be bad because of how ESLint applies all fixes without a chance to review them.

Apart from that, I agree with the proposed rule (it's something I'd like for Elm as well but find is not a standard function unfortunately).

@domdomegg
Copy link
Contributor

The current title I think has them the wrong way around:

Rule proposal: Preferring .filter(...) over .find(...)[0]

Consider updating to:

Rule proposal: Preferring .find(...) over .filter(...)[0]

@armano2 armano2 changed the title Rule proposal: Preferring .filter(...) over .find(...)[0] Rule proposal: Preferring .find(...) over .filter(...)[0] Apr 12, 2023
@domdomegg
Copy link
Contributor

Is this already covered by https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-find.md?

@bradzacher
Copy link
Member

See earlier comment - #6886 (comment)
The question is whether or not a type-aware rule should be created.

@JoshuaKGoldberg
Copy link
Member Author

JoshuaKGoldberg commented Apr 16, 2023

@JoshuaKGoldberg JoshuaKGoldberg added accepting prs Go ahead, send a pull request that resolves this issue and removed triage Waiting for team members to take a look labels Apr 16, 2023
@JoshuaKGoldberg
Copy link
Member Author

Oh and fun fact, https://sourcegraph.com/search?q=context:global+/filter.*%5C%29%5C%5B0%5C%5D/&patternType=standard&sm=1&groupBy=repo shows quite a few examples of people doing the .filter(...)[0] approach in the wild. Nifty!

@Josh-Cena
Copy link
Member

I have a related request: I think you should prefer some over either filter[0] or find if the return value is only used in a Boolean context!

@JoshuaKGoldberg
Copy link
Member Author

JoshuaKGoldberg commented Jan 9, 2024

Whoo that's a complex one 😄. I don't know if it'd be easily feasible to get into this rule... maybe a good followup? Not sure 🤔

@kirkwaiblinger
Copy link
Member

I have a related request: I think you should prefer some over either filter[0] or find if the return value is only used in a Boolean context!

I wonder whether this ought to just be a whole separate rule. I could certainly try to include it as an option for the fix for .filter(...)[0], but then existing code like

if ([1, 2, 3].find(x > 1)) {
}

would not get flagged. So maybe there should just be another rule entirely to prefer .some over .find in boolean contexts. I guess the drawback would be that if this rule just rewrites .filter(...)[0] -> .find(...) no matter what, then that will mean a second pass will be necessary to additionally fix the new rule.

Overall it seems like that rule would have quite a bit more complexity than makes sense just to add as a suggestion for this rule, since we'd have to start asking what we want done with

if ([-1, 0, 1].find(x => x === 0)) {
    // doesn't execute; not the same as [-1, 0 , 1].some(x => x === 0)
}

Thoughts?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepting prs Go ahead, send a pull request that resolves this issue enhancement: new plugin rule New rule request for eslint-plugin package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants