Awaited în TypeScript

Awaited<T> dă tipul valorii pe care o obții cu await din T, desfăcând și Promise-urile imbricate.

Sintaxă
type V = Awaited<Promise<number>>;            // number
type W = Awaited<Promise<Promise<string>>>;   // string

Ce face Awaited

Awaited<T> modelează ce face await: desface un Promise (și orice obiect cu metoda then) și dă tipul valorii din el. Dacă Promise-ul conține tot un Promise, îl desface și pe acela, recursiv. Dacă T nu este un Promise, rămâne neschimbat.

Combinația cea mai des întâlnită este Awaited<ReturnType<typeof f>>: tipul rezultatului unei funcții async, după await. TypeScript folosește Awaited și în tipul lui Promise.all, Promise.race și al cuvântului await.

Pe un union, se aplică pe fiecare variantă: Awaited<Promise<number> | string> este number | string.

Parametri

Parametru Descriere
T Orice tip; de obicei un Promise.

Ce returnează

Tipul valorii după await.

Exemple

Exemplul 1: Tipul datelor încărcate de o funcție async

async function incarcaElev(id: number) {
    await new Promise((r) => setTimeout(r, 5));
    return { id, nume: id === 1 ? "Ana" : "Mihai", note: [9, 10] };
}

type Elev = Awaited<ReturnType<typeof incarcaElev>>;   // { id: number; nume: string; note: number[] }

const cache = new Map<number, Elev>();
async function elev(id: number): Promise<Elev> {
    const gasit = cache.get(id);
    if (gasit) return gasit;
    const e = await incarcaElev(id);
    cache.set(id, e);
    return e;
}

console.log((await elev(1)).nume, (await elev(2)).nume, cache.size);

Rezultat

Ana Mihai 2

Exemplul 2: Desfacere recursivă și union

type A = Awaited<Promise<Promise<string>>>;     // string
type B = Awaited<number>;                       // number (nu este Promise)
type C = Awaited<Promise<boolean> | string>;    // boolean | string

const a: A = "Iași";
const b: B = 42;
const c: C[] = [true, "Cluj"];
console.log(a, b, c);

Rezultat

Iași 42 [ true, 'Cluj' ]

Exemplul 3: Valoarea nu este un Promise

Variabila are tipul valorii desfăcute, deci nu acceptă un Promise.

type N = Awaited<Promise<number>>;
const n: N = Promise.resolve(5);
console.log(n);

Eroarea afișată de tsc

exemplu.mts(2,7): error TS2322: Type 'Promise<number>' is not assignable to type 'number'.

Greșeli frecvente

  • Scrii propriul type Unwrap<T> = T extends Promise<infer U> ? U : T. Nu desface Promise-urile imbricate; folosește Awaited.

Comenzi înrudite

  • Promise<T>: Tipul unei valori care va fi disponibilă mai târziu; T este tipul rezultatului, nu și al erorii.
  • async/await cu tipuri: O funcție async returnează mereu Promise<T>; await scoate valoarea de tip T din Promise.
  • ReturnType: ReturnType<F> dă tipul rezultatului unei funcții; pentru o funcție concretă scrii ReturnType<typeof f>.
  • infer: În ramura extends a unui tip condițional, infer X „prinde” o parte din tip și o dă un nume.