Awaited
When working with async code, you frequently encounter types wrapped in Promises. Awaited is how you unwrap them.
The mental model
Imagine you have a function that fetches data, and you want to extract the exact type of the data it resolves to. If you use ReturnType, you get the Promise wrapper. Awaited simulates the behavior of the await keyword at the type level.
async function fetchConfig() {
return { timeout: 5000, environment: "production" };
}
// Extract the return type:
type ConfigPromise = ReturnType<typeof fetchConfig>;
// => Promise<{ timeout: number, environment: string }>
// Unwrap the Promise to get the actual data type:
type Config = Awaited<ConfigPromise>;
// => { timeout: number, environment: string }
Recursive unwrapping
In JavaScript, if you await a Promise that resolves to another Promise, it automatically unwraps all the way down until it hits a non-Promise value.
Awaited accurately models this behavior. It is recursive.
type Nested = Promise<Promise<Promise<number>>>;
type Unwrapped = Awaited<Nested>;
// => number
Real-world usage: Typing external API responses
This is most commonly seen when you are using an SDK or an ORM (like Prisma) where you don't want to import massive types manually. You can just extract the awaited return type of their query functions.
import { db } from "./database";
// Extract the exact type of the array items returned by the query
type ActiveUser = Awaited<ReturnType<typeof db.getUsers>>[0];
Awaited<Type>recursively unwraps Promises at the type level, exactly mimicking how theawaitkeyword unwraps values at runtime.