Skip to main content
An asynchronous generator function is a construct declared with async function* that combines the pause-and-resume execution model of generators with the non-blocking, Promise-based resolution of asynchronous functions. Invoking this function does not execute its body immediately; instead, it returns an AsyncGenerator object that conforms to both the AsyncIterable and AsyncIterator protocols.

Type Signature

In TypeScript, the return type of an async generator is explicitly typed using the built-in AsyncGenerator<T, TReturn, TNext> interface.
  • YieldType (T): The type of the values emitted by the yield keyword.
  • ReturnType (TReturn): The type of the final value returned by the function when it completes (via the return statement). In the TypeScript standard library interface, this defaults to any.
  • NextType (TNext): The type of the value injected back into the generator when calling .next(value). In the TypeScript standard library interface, this defaults to unknown.

Execution Mechanics

  1. Awaiting and Yielding: Inside the function body, you can use await to pause execution until a Promise settles. You use yield to emit a value to the consumer.
  2. Promise Wrapping: Unlike synchronous generators that return an IteratorResult directly, an async generator’s .next() method always returns a Promise that resolves to an IteratorResult object: { value: T | TReturn, done: boolean }.
  3. Two-way Communication: The generator pauses at each yield. When the consumer calls .next(argument), the generator resumes, and the argument becomes the evaluated result of the yield expression.
  4. Promise Queueing: If multiple .next() calls are made synchronously before previous ones resolve, the async generator queues them internally. Each .next() call waits for the preceding iteration to fully complete (including any internal await operations) before executing, ensuring strict sequential execution.

Syntax Visualization

The following example demonstrates the type annotations, internal await mechanics, and two-way communication via yield. The NextType includes undefined to safely accommodate constructs that do not pass arguments to .next().

Consumption Mechanics

Because the generator yields Promises, it cannot be consumed by a standard for...of loop. It must be consumed asynchronously. Manual Iteration via .next() When calling .next() manually, you can leverage the internal Promise queueing mechanism. Synchronous calls to .next() will automatically wait for their turn in the queue.
Iteration via for await...of TypeScript supports the for await...of statement to automatically consume AsyncIterable objects. This approach automatically awaits each yielded Promise, extracts the value, and terminates when done: true. Note that for await...of calls .next() without any arguments. This means undefined is injected into the generator at every step.
Tired of Poor TypeScript Skills? Fix That With Deep Grasping!Learn More