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 await operator is a unary operator that suspends the execution of an asynchronous function until a Promise is settled (either fulfilled or rejected). In TypeScript, it inherently acts as a static type-unwrapping mechanism, extracting the deeply resolved value type from a Promise or PromiseLike object.

Syntax

await expression;
  • expression: A Promise, a thenable object, or any synchronous value waiting to be resolved.

Type Resolution and Awaited<T>

TypeScript’s type checker evaluates the await operator by recursively unwrapping the Promise type. To model this exact resolution behavior, TypeScript 4.5 introduced the Awaited<T> utility type, which mirrors the recursive unwrapping performed by the await operator.
  • If the operand is of type Promise<T> or PromiseLike<T>, the resulting static type of the await expression is Awaited<T>. Because await and Awaited unwrap promises recursively, if T is itself a Promise, the expression resolves to the deeply unwrapped type. For example, applying await to an operand of type Promise<Promise<string>> resolves to string, not Promise<string>.
  • If the operand is a non-promise type U, the TypeScript type checker simply resolves the static type to U. (Note: At runtime, the JavaScript engine implicitly wraps and unwraps this value via Promise.resolve(), but the TypeScript static type remains U).
export {}; // Ensures the file is treated as a module to allow top-level await

declare const nestedPromise: Promise<Promise<string>>;
declare const syncValue: number;

// TypeScript infers 'result1' as 'string' via Awaited<Promise<Promise<string>>>
const result1 = await nestedPromise; 

// TypeScript infers 'result2' as 'number' via Awaited<number>
const result2 = await syncValue; 

Execution Context

The await operator is syntactically valid only in specific execution contexts:
  1. Inside a function, method, or arrow function marked with the async modifier.
  2. Inside an async generator function (async function*).
  3. At the top level of a module (Top-Level Await), provided the TypeScript compiler target is es2017 or higher and the module option is set to a compatible format (e.g., es2022, esnext, node16, nodenext).
// Valid: Inside an async function
async function process(): Promise<void> {
    const data = await Promise.resolve(42);
}

// Valid: Top-level await (in a module context)
export const config = await Promise.resolve({ env: "prod" });

Control Flow and Rejection

When the JavaScript engine encounters await, it yields execution control back to the calling context and pushes the remainder of the async function onto the microtask queue.
  • Fulfillment: If the promise fulfills, the await expression evaluates to the fulfillment value, and execution resumes.
  • Rejection: If the promise rejects, the await operator synchronously throws the rejection reason as an exception within the async function’s execution context. This requires standard try...catch blocks for error interception.
async function handleRejection(): Promise<void> {
    try {
        // If the promise rejects, execution immediately jumps to the catch block
        const value = await Promise.reject(new Error("Failure"));
    } catch (error: unknown) {
        // 'error' contains the rejection reason
    }
}
Master TypeScript with Deep Grasping Methodology!Learn More