Skip to content

for await and nullish coalescing causes name collision #37418

@rynti

Description

@rynti

It seems I stumbled on a bug in TypeScript when I used a for await loop containing two nullish coalescing operations inside an if condition. When targeting ES2017 or less, TypeScript uses _b as a temporary variable holding the iterator, calling _b.next() for every iteration. However, in the if condition _b is overwritten as another temporary variable. See the playground link to see the generated JS code, the bug happens inside the outerIterator function.

TypeScript Version: v3.9.0-dev.20200315

Search Terms: for await async iterable iterator name collision next nullish coalescing

Code

async function* getIterator(): any {
    yield { member: 1 };
    yield { member: 2 };
    yield { member: 3 };
}

async function* outerIterator(): any {
  for await (const row of getIterator()) {
    // This line causes a name collision with by setting a variable `_b`,
    // which is also used to hold the iterator above:
    if ((row.member ?? null) === (row.member ?? null)) {
      yield row;
    }
  }
}

async function main() {
  console.log("main()");
  for await (const row of outerIterator()) {
    console.log(row);
  }
}
main().catch(e => console.error(e));

Expected behavior:
In the console:

main()
{ member: 1 }
{ member: 2 }
{ member: 3 }

Actual behavior:

main()
{ member: 1 }
TypeError: _b.next is not a function
    at outerIterator_1 ...

Playground Link:
Playground Link

Related Issues:
Not sure, but maybe #28849 is related.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptDomain: JS EmitThe issue relates to the emission of JavaScriptEffort: ModerateRequires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual".Help WantedYou can do this

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions