Skip to content

Bug: [await-thenable] False positive for for await...of value which is AsyncIterable | Iterable #10111

Closed as not planned
@haines

Description

@haines

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.
  • I have searched for related issues and found none that matched my issue.
  • I have read the FAQ and my problem is not listed.

Playground Link

https://typescript-eslint.io/play/#ts=5.4.3&fileType=.tsx&code=IYZwngdgxgBAZgV2gFwJYHsICoYFNhQAWAMqhLgBQD6IyATvgLYBcMASvgCbABGANrgDK9JgB4AqmWQAOAIJ06wMAD4AlK1nhoAcVzlFydHVG06ZAOYAaGADd0qTtaSdccMrk7KYAbwBQMGDBUXD5OGAAiVEYABwFGPWRgNEwYdEZUZGQPcN8AX19fXAAPaKNkGFBIWEQUDAgYPnRzUnIQClMmAH5WDmBufiERYEYJKTkFJTVWAAU6NNQQXFE7By8-AKhMWgb3EBgAXhgO4ZhOvAISd3ahxlUYVgBtAF0AbgKAuCMKgHdgDJgKJsINs%2BO5UnAdq07usAjAgSB0AIAHSNcwUUHkVT%2BGD5XJAA&eslintrc=N4KABGBEBOCuA2BTAzpAXGUEKQAIBcBPABxQGNoBLY-AWhXkoDt8B6AQwHd3K78ALRE3YAjJOijdoTSODABfEPKA&tsconfig=N4KABGBEDGD2C2AHAlgGwKYCcDyiAuysAdgM6QBcYoEEkJemy0eAcgK6qoDCAFutAGsylBm3TgwAXxCSgA&tokens=false

Repro Code

// contrived example

async function* eachLine(_stream: ReadableStream<Uint8Array>): AsyncGenerator<string, void, undefined> {
  yield "implementation omitted"
}

export async function logLines(stream?: ReadableStream<Uint8Array>): Promise<void> {
  const lines = stream ? eachLine(stream) : ["some", "defaults"];

  for await (const line of lines) {
    console.log(line)
  }
}

ESLint Config

module.exports = {
  "rules": {
    "@typescript-eslint/await-thenable": "warn"
  }
}

tsconfig

{
  "compilerOptions": {
    "strictNullChecks": true
  }
}

Expected Result

If a value is AsyncIterable | Iterable, you need a for await...of loop to iterate over it, so the linter doesn't complain.

Actual Result

await-thenable reports

Unexpected `for await...of` of a value that is not async iterable. 8:3 - 8:34
> Convert to an ordinary `for...of` loop.

If you apply the suggestion, which in the example is

for (const line of lines) {

then the linter is satisfied but the code is broken and the compiler knows it:

2488: Type 'AsyncGenerator<string, void, undefined> | never[]' must have a '[Symbol.iterator]()' method that returns an iterator. 8:22 - 8:27

Additional Info

It's fine to use for await...of to iterate over a sync iterable. It makes sense not to use this construct if you know that you have a sync iterable, but if you may have either an async iterable or a sync one, then you need it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglocked due to agePlease open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing.package: eslint-pluginIssues related to @typescript-eslint/eslint-plugintriageWaiting for team members to take a look

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions