0

I'm running into a @typescript-link no-unnecessary-condition warning with the following code (source):

async function waitForOneOf(locators: Locator[]): Promise<WaitForRes> {
  // timeToWait can be long because if it fails, the whole test fails anyway.
  const timeToWait = 5000;
  const res = await Promise.race([
    ...locators.map(async (locator, index): Promise<WaitForRes> => {
      let timedOut = false;
      await locator
        .waitFor({ state: 'visible', timeout: timeToWait })
        .catch(() => {
          timedOut = true;
        });
      return [timedOut ? -1 : index, locator];
    }),
  ]);
  if (res[0] === -1) {
    throw new Error(`no locator visible before timeout ${locators.toString()}`);
  }
  return res;
}

The problem is the line

return [timedOut ? -1 : index, locator];

Eslint identifies timedOut is always falsy because let timedOut = false. However, I think this is incorrect (it is not always falsy) becaue the value of timedOut may be changed in the catch function because it is an arrow function, so the timedOut variable is accessible to it.

Is my understand correct-- this eslint error is incorrect? Or am I misunderstanding how variables work in JS/TS in this scenario?

Patrick Kenny
  • 4,515
  • 7
  • 47
  • 76

2 Answers2

1

This is due to this famous issue.

timedOut is incorrectly inferred as false.

You can fix it with a type assertion : let timedOut = false as boolean;

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
0

Actually, you can define type of timedOut

let timedOut: true | false = false;

and type would be inferred correct.

Yaroslavm
  • 1,762
  • 2
  • 7
  • 15
  • No, see https://github.com/microsoft/TypeScript/issues/9998 – Matthieu Riegler Jul 16 '23 at 14:11
  • @MatthieuRiegler strange thing. I believe that you're right, but my lint doesn't show any error if I define let timedOut: true | false = false; , for example. (I don't prefer type casting via as) – Yaroslavm Jul 16 '23 at 14:21