W TypeScript funkcje asynchroniczne (async/await) zawsze zwracają Promise. Typ wartości zwracanej jest określany w ten sposób: Promise<Type>. Przy opisywaniu funkcji ważne jest, aby wyraźnie typizować wynik, aby TypeScript poprawnie działał z typami wewnątrz promisa. Błędy typizacji mogą wystąpić, jeśli wartości pośrednie nie odpowiadają tym, co zostało zadeklarowane.
Funkcja asynchroniczna:
async function fetchUser(id: number): Promise<User> { const response = await fetch(`/api/user/${id}`); const data: User = await response.json(); return data; }
Jeśli funkcja powinna zwrócić błąd lub odrzucenie, to typ promisa nie powinien opisywać błędu bezpośrednio (Promise<Error>), ponieważ odrzucenie promisa nie jest typizowane, a przechwytywane przez catch.
Typizacja łańcuchów promisów jest ważna:
function getNumber(): Promise<number> { return Promise.resolve(42); } getNumber().then(val => val.toFixed(2)); // TypeScript wie, że val jest liczbą
Pytanie: Czy funkcja asynchroniczna może zwracać coś innego poza promisem?
Odpowiedź: Nie. Funkcja asynchroniczna zawsze zwraca obiekt Promise. Jeśli wyraźnie zwrócimy nie-promise, TypeScript automatycznie opakuje wartość zwracaną w promise.
async function test() { return 1; } const result = test(); type ResultType = typeof result; // Promise<number>
Historia
Programista napisał funkcję bez wyraźnej typizacji wartości zwracanej, zakładając, że zwraca obiekt określonego typu. Po zmianie logiki funkcja zaczęła zwracać inny typ, co nie zostało od razu zauważone, ponieważ TypeScript, bazując na wnioskowaniu typu, nie zgłaszał błędów. W rezultacie błędy ujawniły się dopiero w czasie wykonywania, gdy konsument funkcji próbował wywołać nieistniejącą właściwość.
Historia
W jednym projekcie łańcuchy promisów nie były typizowane. Próba odwołania się do nieistniejącej metody na wyniku prowadziła do błędów. Tak więc wynik then(response => response.data) był uważany za any, a błąd łapania pól lub metod ujawniał się tylko w czasie wykonywania. Błąd trafił do produkcji i został wykryty dopiero dzięki użytkownikom.
Historia
Funkcję asynchroniczną zadeklarowano z typem Promise<Error>, sądząc, że pozwoli to łapać błędy, ale w rzeczywistości błędy nie były przekazywane przez throw, a promise był odrzucany z innym typem wartości. Doprowadziło to do niejawnego mieszania błędów i valids wartości, a także do pojawienia się błędów w logice przetwarzania wyników promisów.