typescript-eslint icon indicating copy to clipboard operation
typescript-eslint copied to clipboard

Rule proposal: Prefer Array.prototype.some() over Array.prototype.find() in boolean contexts

Open kirkwaiblinger opened this issue 1 year ago • 3 comments

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

My proposal is suitable for this project

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

Description

Filing this to follow up on a conversation here: https://github.com/typescript-eslint/typescript-eslint/issues/6886#issuecomment-1883744148

The idea would be to create a rule that flags unexpected usage of Array find() where a boolean array callback might make more sense (and perhaps corresponding behavior for similar array methods).

Note that this has overlapping domain with the strict-boolean-expressions rule. If strict-boolean-expressions is configured sufficiently strictly, this rule would not be needed. However, users may want to have flexibility to not have to use strict-boolean-expressions, but still flag the array methods in this proposal.

Fail Cases

if ([1, 2, 3].find(x => x % 2 === 0)) {
    // do something
}

const notFound = !["a", "b", "c"].find(x => x === "not here");

Pass Cases

if ([1, 2, 3].some(x => x % 2 === 0)) {
    // do something
}

const notFound = !["a", "b", "c"].some(x => x === "not here");

Additional Info

No response

kirkwaiblinger avatar Feb 05 '24 02:02 kirkwaiblinger

faithfinder from Twitch Chat noted that an equivalent exists in eslint-plugin-unicorn: https://github.com/sindresorhus/eslint-plugin-unicorn/blob/d76f8a2f57bfc2ce30fe48c339203c68e8211476/docs/rules/prefer-array-some.md. Thanks!

For context, our rules generally are able to use type information to determine whether something is an array vs. just so happens to be used in an array-like way. Similar to https://github.com/typescript-eslint/typescript-eslint/issues/6886#issuecomment-1503962282:

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

declare const jerkCode: JerkCode<string>;

if (jerkCode.find(item => item === "aha")) {
  // ...
}

JoshuaKGoldberg avatar Feb 08 '24 15:02 JoshuaKGoldberg

Honestly I don't think there's too much need here for a type-aware clone of that rule. .find that takes a callback is a rare enough method that you're not going to get many false positives, if any, in the broader ecosystem.

bradzacher avatar Feb 08 '24 20:02 bradzacher

I wish we had good tooling to see, for edge cases like this, how many violations they'd find in (some arbitrary slice of the open source TypeScript world)...

JoshuaKGoldberg avatar Feb 09 '24 14:02 JoshuaKGoldberg

https://github.com/typescript-eslint/typescript-eslint/issues/8453 does bring up an interesting additional context that could be checked. Might be more worthwhile of a rule if there's it's more generally to prefer .some() and .every() wherever applicable, and now we know of 2 distinct examples of patterns that could be flagged. Perhaps there are more?

kirkwaiblinger avatar Mar 22 '24 04:03 kirkwaiblinger