Awaited: тип для промисов
Awaited<T>— утилитарный тип TypeScript, который рекурсивно разворачивает тип промиса:Awaited<Promise<string>>даётstring,Awaited<Promise<Promise<number>>>даётnumber.
Зачем нужно
До появления Awaited (TypeScript 4.5) извлечь тип разрешённого значения промиса было громоздко — нужно было писать ReturnType<typeof fn> с ручным раскрытием. Awaited решает задачу рекурсивно и корректно обрабатывает thenable-объекты, что критично при типизации async/await-кода.
Где используется
- Типизация результатов
Promise.all,Promise.allSettled,Promise.race - Утилитарные функции, принимающие или возвращающие промисы
- Вычисление типа возвращаемого значения async-функции через
ReturnType - Generic-обёртки над fetch/API-вызовами
Основной контент
Базовое использование
type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<number>>>; // number
type C = Awaited<string>; // string (не промис — возвращается как есть)
type D = Awaited<Promise<string | null>>; // string | null
С ReturnType async-функций
async function fetchUser(id: number) {
const res = await fetch(`/api/users/${id}`);
return res.json() as Promise<{ id: number; name: string }>;
}
// Без Awaited пришлось бы писать сложнее
type User = Awaited<ReturnType<typeof fetchUser>>;
// { id: number; name: string }
function processUser(user: User) {
console.log(user.name);
}
Promise.all и Awaited
const results = await Promise.all([
fetch("/api/users").then((r) => r.json() as Promise<User>),
fetch("/api/posts").then((r) => r.json() as Promise<Post>),
]);
// results: [User, Post]
// TypeScript автоматически применяет Awaited к каждому элементу кортежа
type Results = Awaited<typeof results>; // [User, Post]
Пользовательский generic с Awaited
// Функция, которая принимает промис или значение и всегда возвращает Promise
async function wrap<T>(value: T | Promise<T>): Promise<Awaited<T>> {
return value as Awaited<T>;
}
const a = await wrap(42); // number
const b = await wrap(Promise.resolve("hello")); // string
Реализация Awaited внутри TS
// Упрощённое определение из стандартной библиотеки
type Awaited<T> =
T extends null | undefined
? T
: T extends object & { then(onfulfilled: infer F, ...args: any): any }
? F extends (value: infer V, ...args: any) => any
? Awaited<V>
: never
: T;
Частые ошибки
- Использовать
Promise<ReturnType<T>>вместоAwaited<ReturnType<T>>— не раскрывает вложенные промисы. - Забывать что
Awaited<string>=string— тип не требует промиса, он просто «разворачивает» если промис есть. - Путать с
Promise<T>—Awaitedизвлекает тип из промиса, а не создаёт промис.
Связанные темы
- ReturnType, Parameters, InstanceType
- Conditional types
- Infer -- извлечение типов
- Типизация API-ответов
- _MOC TypeScript