Object & Function Types

Awaited<T>

Recursively unwraps the resolved type of a Promise or nested Promises, giving you the eventual value type.

Definition

TypeScript
type Awaited<T> = T extends null | undefined
  ? T
  : T extends object & { then(onfulfilled: infer F, ...args: infer _): any }
    ? F extends (value: infer V, ...args: infer _) => any
      ? Awaited<V>
      : never
    : T;

Examples

Unwrapping Promises
type A = Awaited<Promise<string>>;
// string

type B = Awaited<Promise<Promise<number>>>;
// number (recursively unwrapped)

type C = Awaited<boolean | Promise<string>>;
// boolean | string
Async Function Return Types
async function fetchUser(id: string) {
  const res = await fetch(`/api/users/${id}`);
  return res.json() as Promise<{ name: string; email: string }>;
}

type User = Awaited<ReturnType<typeof fetchUser>>;
// { name: string; email: string }

async function processUser() {
  const user: User = await fetchUser("123");
  console.log(user.name);
}
Promise.all Results
async function loadData() {
  const [users, posts, comments] = await Promise.all([
    fetch("/api/users").then(r => r.json()) as Promise<string[]>,
    fetch("/api/posts").then(r => r.json()) as Promise<number[]>,
    fetch("/api/comments").then(r => r.json()) as Promise<boolean[]>,
  ]);

  type Users = Awaited<Promise<string[]>>; // string[]
  return { users, posts, comments };
}

Common Use Cases

  • 1Extracting the resolved value type from async functions
  • 2Typing variables that store awaited promise results
  • 3Working with Promise.all and Promise.race result types
  • 4Unwrapping deeply nested promise chains
  • 5Building type-safe async utility functions

Understanding Awaited<T>

Awaited<T> recursively unwraps the type inside a Promise, giving you the eventual resolved value type. For Promise<string>, it returns string. For Promise<Promise<number>>, it recursively unwraps to number. For non-promise types, it returns the type as-is.

This utility type was added in TypeScript 4.5 and models what the await keyword does at the type level. Before Awaited existed, developers had to write their own recursive unwrapping types, which were error-prone and didn't handle edge cases like thenable objects.

The most common use of Awaited is with ReturnType for async functions. Since async functions return a Promise, ReturnType<typeof asyncFn> gives you Promise<T>. To get just T, you wrap it: Awaited<ReturnType<typeof asyncFn>>. This pattern is ubiquitous in Next.js applications for typing the resolved data from server-side fetches.

Awaited also handles union types correctly. If T is boolean | Promise<string>, the result is boolean | string—each union member is processed independently, with promises being unwrapped and non-promises passing through.

The implementation handles thenable objects (objects with a then method), not just native Promises. This means it works correctly with promise-like objects from older libraries or custom implementations.

Awaited is the key to making Promise.all, Promise.race, Promise.allSettled, and Promise.any type-safe. The TypeScript standard library uses Awaited internally to type these methods, ensuring that the resolved array or value has the correct unwrapped types.

Related Types

More Object & Function Types

Explore TypeScript Types

Browse our complete reference of 30 TypeScript utility types with definitions, examples, and explanations.