Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The for-await-of statement creates a loop that iterates over asynchronous iterable objects—objects that implement the [Symbol.asyncIterator]() method. It sequentially pauses the execution of the containing async function or block at the loop header until each yielded Promise resolves, extracting the fulfilled value into the loop variable before executing the block.
// Execution pauses at the loop header until the current iteration's Promise resolves
for await (const variable of iterable) {
  // By the time execution reaches here, 'variable' contains the resolved value
}

Technical Mechanics

Under the hood, the for-await-of loop interacts with the AsyncIterator protocol. When the loop initializes, it calls the [Symbol.asyncIterator]() method on the target object to retrieve an asynchronous iterator. During each iteration:
  1. The loop invokes the next() method on the iterator.
  2. next() returns a Promise<IteratorResult<T>>.
  3. The loop implicitly awaits this Promise at the loop header.
  4. Upon resolution, if the IteratorResult has done: false, the value property is assigned to the loop variable, and the block executes.
  5. If the IteratorResult has done: true, the loop terminates.

TypeScript Typing

TypeScript strictly types the for-await-of loop using the built-in AsyncIterable<T> and AsyncIterator<T> interfaces. The loop variable’s type is automatically inferred based on the generic type parameter T of the iterable.
// The generator returns an AsyncGenerator<number, void, unknown>
// which implements AsyncIterable<number>
async function* generateAsyncNumbers(): AsyncGenerator<number> {
  yield Promise.resolve(1);
  yield Promise.resolve(2);
}

async function processNumbers() {
  // TypeScript infers 'num' as type 'number'
  for await (const num of generateAsyncNumbers()) {
    console.log(num);
  }
}

Synchronous Iterable Fallback

If the target object does not implement [Symbol.asyncIterator]() but does implement the synchronous [Symbol.iterator]() (such as a standard Array), for-await-of will consume the synchronous iterable. If the synchronous iterable yields Promises (e.g., Iterable<Promise<T>>), the loop will await each Promise sequentially.
const promiseArray: Iterable<Promise<string>> = [
  Promise.resolve("A"),
  Promise.resolve("B")
];

async function processPromises() {
  // TypeScript infers 'char' as type 'string', unwrapping the Promise
  for await (const char of promiseArray) {
    console.log(char);
  }
}

Compiler Configuration

To use for-await-of in TypeScript, specific tsconfig.json compiler options must be configured depending on your target environment:
  • lib: Must include "ES2018.AsyncIterable" (or a broader library like "ES2018") to provide the global type definitions for Symbol.asyncIterator, AsyncIterable, and AsyncIterator.
  • target: If set to "ES2018" or higher, TypeScript emits native for-await-of syntax. If targeting older environments (such as "ES5" or "ES6"), TypeScript automatically downlevels the loop using the __asyncValues helper function.
  • Downleveling: Unlike synchronous iteration (for...of), for-await-of does not require the "downlevelIteration": true flag to be downleveled. TypeScript always transpiles it when targeting pre-ES2018 environments. However, a runtime polyfill for Symbol.asyncIterator must be present in the execution environment for the emitted code to function correctly.
Master TypeScript with Deep Grasping Methodology!Learn More