useIterableCallbackReturn should be split into two separate rules #8005
Closed
theshadow27
started this conversation in
Rule suggestion
Replies: 2 comments 1 reply
-
|
One common mistake happens by misuse of .forEach() is that a Promise is unintentionally returned. For example: foo.forEach(async () => {
await doSomething();
});This will cause a floating promise because .forEach() completely ignores the returned promise. |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Since this rule is a direct port of https://eslint.org/docs/latest/rules/array-callback-return, I think adding an option for this makes the most sense. It's what the source rule does. |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Problem
Per the docs on useIterableCallbackReturn
The
useIterableCallbackReturnrule conflates two completely different concerns:This issue affects many codebases:
This forces developers to choose between:
This was addressed in #6473, where there seems to be a fundamental dispute between:
vs
I personally agree with the 2nd, but respect the reasoning behind the first. There's no reason to force everyone into this choice, when it could easily be separated.
Real-world false positives
From a production codebase upgraded from 1.x -> 2.x, here are patterns the rule incorrectly flags:
1. Console logging (debugging/reporting)
2. Set/Map mutations
3. Builder patterns
4. Callback execution
5. Closure Binding (even to void functions)
Why this matters
None of these are bugs. They're all correct, idiomatic TypeScript/JavaScript. The return values are incidental to methods designed for side effects.
Meanwhile, the actually useful checks (missing returns in map, filter, etc.) are bundled with this noise, forcing teams to disable the entire rule.
Proposed solution
Option A: Split into two rules:
noMissingIterableReturn(or keep current name).map,.filter,.every,.some,.find,.findIndex,.flatMap,.reduce,.sort, etc.noForEachReturn(new rule, off by default).forEachOption B: Add Configuration Option
If splitting is too disruptive, add a config option:
{ "useIterableCallbackReturn": { "checkForEach": false // default: true } }Have you considered the alternatives?
1. Disable the rule completely
{ "linter": { "rules": { "suspicious": { "useIterableCallbackReturn": "off" } } } }Rejected: Disabling the rule entirely loses the valuable checks for map, filter, etc:
2. wrap everything in
bracketsorvoidnote that the return value is still ignored!
So assuming that was really a bug, what does this gain?
3. Change to
for:ofloops?that's a
+2for what? I picked biome because it has concise defaults. This is worse.Related
lint/nursery/useIterableCallbackReturnincorrectly flags functions that returnvoidas returning a value #6617 claims it cannot be addressed without type inference, but does not consider separating it into two rules.useIterableCallbackReturncomplains incorrectly about return values #7247 duplicated useIterableCallbackReturn should allow forEach arrow callback return a value #6473 , which recommends curly braces-The recent addition of void support (💅
lint/nursery/useIterableCallbackReturnincorrectly flags functions that returnvoidas returning a value #6617, fix(lint/suspicious/useIterableCallbackReturn): single-expression void arrow function #7564, ci: release #7478) helps but doesn't solve the fundamental problem: developers must choose between valuable bug detection and hundreds of false positives.But the alternative here ("separate them into 2 rules") was not considered.
Expected behavior
I should be able to:
Beta Was this translation helpful? Give feedback.
All reactions