Skip to content

Union of Generator and AsyncGenerator introduces spurious undefined next() value path #42439

Closed
@cefn

Description

@cefn

Bug Report

I was creating a coroutine-based interactive prompt library. It can consume either synchronous or asynchronous co-routines.

There doesn't seem to be any runtime issue associated with this approach, (in some configurations the library harmlessly awaits on a synchronous generator.next()).

However, any function which is declared as fulfilling a union of async+sync generators faces a compile error when a spurious undefined value is indicated as possible from a yield even though the next() call only accepts strings.

🔎 Search Terms

yield, undefined, typescript, asyncgenerator, generator

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about AsyncGenerator

⏯ Playground Link

Playground link with relevant code

💻 Code

type SyncSequenceFactory = () => Generator<string, string, string>;

type AsyncSequenceFactory = () => AsyncGenerator<string, string, string>;

type SequenceFactory = SyncSequenceFactory | AsyncSequenceFactory

const syncFactory: SyncSequenceFactory = function* (){
  let name = "";
  while(!name){
    name = yield "What is your name?"
  }
  return `That's the end of the game, ${name}`
} 

const asyncFactory: AsyncSequenceFactory = async function* (){
  let name = "";
  while(!name){
    name = yield "What is your name?"
  }
  return `That's the end of the game, ${name}`
} 

const looserSyncFactory: SequenceFactory = function* (){
  let name = "";
  while(!name){
    name = yield "What is your name?"
  }
  return `That's the end of the game, ${name}`
} 

const looserAsyncFactory: SequenceFactory = async function* (){
  let name = "";
  while(!name){
    name = yield "What is your name?"
  }
  return `That's the end of the game, ${name}`
} 

🙁 Actual behavior

Compiler reports Type 'string | undefined' is not assignable to type 'string'.

🙂 Expected behavior

I don't believe this possible execution path is actually made possible by the union, since it is not possible in either of the unioned cases.

Metadata

Metadata

Assignees

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.RescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions