TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Iterators/Generators, next(), and unsafe yield statement types

Open Renegade334 opened this issue 10 months ago • 0 comments

Acknowledgement

  • [X] I acknowledge that issues using this template may be closed without further explanation at the maintainer's discretion.

Comment

🔎 Search Terms

iterator generator yield next

🕗 Version & Regression Information

Current behaviour has existed since 3.6.0.


With upcoming changes to iterators, I wonder whether it might be worth quickly revisiting the behaviour of the next() iterator method.

As discussed at #30790, when interacting with iterators manually, the compiler will always consider it valid if next() is called with zero-arity, even if TNext is of a type that cannot be void/undefined. The rationale for allowing this is that any parameter passed to the first call to next() gets thrown away, so it should be valid to allow the parameter to be absent.

This does have some type safety implications as originally discussed, but this also causes a related problem with the type of the yield statement in generators, which I don't think has ever been raised before:

function *g(): Generator<null, string, number> {
  const a = yield null; // const a: number
  return a.toString(16);
}

const it = g();
it.next();
it.next(); // TypeError: a is undefined

The function signature of next() allows the second call to be made without a parameter, but the compiler assumes that the type of the yield statement will always be TNext, and never be undefined. Although it violates the semantic intention of the generator signature, it seems like yield potentially returning undefined is a forced possibility if next() always allows calls with zero parameters, which was discussed previously and considered necessary.

Even if there's no alternative way to define next(), I wonder if the question of how to handle yield specifically needs considering.

related: #58243

Renegade334 avatar Apr 30 '24 23:04 Renegade334