question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Catch when callbacks are missing a return.

See original GitHub issue

Search Terms

  • array callback return
  • eslint array-callback-return
  • catch missing return for callbacks

Suggestion

TypeScript does not recognise this as an error even though it clearly is - findIndex takes a callback which should return a boolean, returning an (implicit) undefined is IMO in 99% of cases a mistake.

[1,2,3].findIndex(e => {
  e === 1
})

I also think that if there is an explicit return of a falsey value such as null or undefined, then that should be fine. It’s the lack of any return at all which should trigger an error, in my eyes.

I’m aware that ESLint can do this but not everyone uses ESLint, also ESLint can be a huge pain to configure sometimes, especially when Prettier, TypeScript and other things are involved.

Use Cases

It will definitely catch errors, IMHO, for people who don’t use ESLint or do not have the rule array-callback-return.

Examples

No error:

[1,2,3].findIndex(e => 
  e === 1
)

No error:

[1,2,3].findIndex(e => e === 1)

A warning/errror: “Did you forget a return?”

[1,2,3].findIndex(e => {
  e === 1
})

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:1
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
jcalzcommented, Jan 28, 2020

Until and unless this gets implemented, you might consider modifying the standard library typings in your local code base to get something close to this behavior:

interface Array<T> {
  findIndex2<B extends (void extends B ? boolean : unknown)>(
    cb: (v: T, i: number, arr: this) => B): number
}

[1, 2, 3].findIndex2(e => e === 1); // okay
[1, 2, 3].findIndex2(e => { e === 1 }); // error! void is not assignable to boolean
[1, 2, 3].findIndex2(e => { e === 1; return undefined; });// okay
[1, 2, 3].findIndex2(e => { e === 1; return; }); // error, void is not assignable to boolean 🤷‍♂️

Playground link

This is ugly enough that I wouldn’t seriously suggest doing it upstream. Less ugly is just requiring that the callback return boolean:

interface Array<T> {
  findIndex2(cb: (v: T, i: number, arr: this) => boolean): number
}

[1, 2, 3].findIndex2(e => e === 1); // okay
[1, 2, 3].findIndex2(e => { e === 1 }); // error! void is not assignable to boolean
[1, 2, 3].findIndex2(e => { e === 1; return undefined; });// error! undefined is not boolean
[1, 2, 3].findIndex2(e => { e === 1; return; }); // error, void is not assignable to boolean 

Playground link

which also wouldn’t be suitable for upstream because it would likely break a lot of existing code that relies on truthy/falsy returns.

0reactions
falsandtrucommented, Jan 28, 2020

Listing all the types without void would resolve this as follows.

interface Array<T> {
    findIndex(predicate: (value: T, index: number, obj: T[]) => undefined | boolean | number | bigint | string | symbol | null | object, thisArg?: any): number;
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Catching Errors thrown by callback functions - Stack Overflow
Of course it doesn't - someFunction is asynchronous and returns a promise. try / catch cannot catch asynchronous errors (promise rejections) ...
Read more >
JavaScript Callbacks Variable Scope Problem - Pluralsight
The callbackClosure function returns a function that invokes the actual callback with an explicit copy of i as an argument. 1var array =...
Read more >
Active Record Callbacks - Ruby on Rails Guides
Running Callbacks; Skipping Callbacks; Halting Execution ... Callbacks are methods that get called at certain moments of an object's life cycle.
Read more >
Reading 20: Callbacks and Graphical User Interfaces
In this reading we talk about callbacks, in which an implementer calls a ... The use of the callback is synchronized within the...
Read more >
New rule: callback-return · Issue #298 · standard ... - GitHub
preceding a return statement. This rules decides what is a callback based on the name of the function being called. By default the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found