Search code examples
typescripteslinttypescript-eslint

Why is @typescript-eslint/promise-function-async triggered by this code?


I have this code in my little project:

close(flush = false): void {
    if (this.ws?.CLOSING || this.ws?.CLOSED) {
        return;
    }

    if (flush) {
        // I really don't know how to fix that
        // eslint-disable-next-line @typescript-eslint/promise-function-async
        const sendPromises = this.state.queue.map((message) =>
            this.sendAsync(message)
        );
        void Promise.all(sendPromises).then(() => this.ws?.close());
    } else {
        this.ws?.close();
    }
}

When I run xo (which uses typescript-eslint) on it, @typescript-eslint/promise-function-async fails. I made a few changes, but it still fails. Can anyone give me an explanation about why this doesn't work?

What I tried:

// first
const sendPromises: Promise<void> = this.state.queue.map((message) => this.sendAsync(message));
// second
const sendPromises = this.state.queue.map((message): Promise<void> => this.sendAsync(message));

Solution

  • Here is the description of the @typescript-eslint/promise-function-async rule:

    Requires any function or method that returns a Promise to be marked async.

    With example for incorrect code:

    const arrowFunctionReturnsPromise = () => Promise.resolve('value');
    
    function functionReturnsPromise() {
      return Promise.resolve('value');
    }
    

    and correct code:

    const arrowFunctionReturnsPromise = async () => Promise.resolve('value');
    
    async function functionReturnsPromise() {
      return Promise.resolve('value');
    }
    

    Your code fails the first line of the example. More specifically the problem is here:

    const sendPromises = this.state.queue.map((message) =>
      this.sendAsync(message)
    );
    

    You're calling .map() with an arrow function that produces a promise, so according to the rule, you have to mark it as async like so:

    const sendPromises = this.state.queue.map(async (message) =>
    //                                        ^^^^^
      this.sendAsync(message)
    );