Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cefn opened this issue Jan 21, 2021 · 0 comments · Fixed by #51196
Closed

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

cefn opened this issue Jan 21, 2021 · 0 comments · Fixed by #51196
Assignees
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@cefn
Copy link

cefn commented Jan 21, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
5 participants