Represent staged computation that yields intermediate values and a final result.
Typed pipelines
TypeScript · Interface
Generator<T, TReturn, TNext> describes a generator as a typed iterator that is also iterable. Its parameters separately model yielded values, the final return value, and values passed to next.
Generator<T, TReturn, TNext> models a generator as an iterable iterator with explicit yielded, returned, and next-input types. It requires next, return, and throw methods and supplies the iterator protocol through Symbol.iterator.
interface Generator<T = unknown, TReturn = any, TNext = unknown> extends Iterator<T, TReturn, TNext> {
next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
return(value: TReturn): IteratorResult<T, TReturn>;
throw(e: any): IteratorResult<T, TReturn>;
[Symbol.iterator](): Generator<T, TReturn, TNext>;
}| Name | Type | Description |
|---|---|---|
T | unknown | Type yielded by the generator. |
TReturn | any | Type returned when the generator completes. |
TNext | unknown | Type accepted by next when resuming the generator. |
IteratorResult<T, TReturn> from next, return, and throw; Generator<T, TReturn, TNext> from Symbol.iterator.
function* numbers(): Generator<number, string, boolean> {
const includeMore = yield 1;
if (includeMore) yield 2;
return "done";
}
const iterator = numbers();
iterator.next();
iterator.next(true);
const result = iterator.next();
console.log(result.done, result.value);This generator yields numbers, accepts a boolean through next, and returns a string when complete.
Typed pipelines
Protocol implementations
Generator APIs
Generator<T, TReturn, TNext> extends Iterator<T, TReturn, TNext>. It also requires return and throw and implements Symbol.iterator, so the generator is itself iterable.
Follow-up: How do you model a generator that yields strings, returns a number, and receives dates? Use Generator<string, number, Date>.
T is the type produced by yield, TReturn is the type produced when the generator finishes, and TNext is the type accepted by next. This separates intermediate values from the final result and incoming values.
Follow-up: Why can next have a tuple-union parameter? It permits either next() or next(value) according to the generator's input type.
Generator's next, return, and throw methods produce IteratorResult<T, TReturn>. IteratorResult is a discriminated union, so done distinguishes yielded results from the completed return result.
Follow-up: What should code do before using result.value as TReturn? Narrow on done === true, because value has different meanings in the two union branches.
IteratorIteratorResultIteratorYieldResultIteratorReturnResultIterable