TS Async / Promises
TypeScript types async functions and Promises seamlessly. An async function always returns a Promise<T>; await unwraps it.
async / await
TS
async function getUser(id: number): Promise<User> {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json() as Promise<User>;
}
// Caller
const u = await getUser(42); // U (TS unwraps the promise)
Promise<T> return type
Even if your function returns a value directly, async wraps it in a Promise:
TS
async function getTitle(): Promise<string> {
return 'TypeScript'; // returns Promise<string>
}
Errors as exceptions
TS
async function load() {
try {
return await getUser(42);
} catch (e) {
// In TS 4.4+, e is unknown by default
if (e instanceof Error) console.error(e.message);
}
}
Parallel work
TS
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json() as Promise<User[]>),
fetch('/api/posts').then(r => r.json() as Promise<Post[]>),
]);
// Best-of-many
const winner = await Promise.race([slowApi(), fastApi()]);
// Wait for all, even if some fail
const results = await Promise.allSettled([a(), b(), c()]);
Type inference with await
TS
async function main() {
const u = await getUser(1); // User
const us = await Promise.all([1, 2, 3].map(getUser)); // User[]
}
Awaited<T> utility
TS
type T1 = Awaited<Promise<string>>; // string type T2 = Awaited<Promise<Promise<number>>>; // number — recursive
Tip: Always handle the rejection case. A top-level
process.on('unhandledRejection', …) (Node) or window.addEventListener('unhandledrejection', …) (browser) catches bugs you missed.Example
Example
async function getUser(id: number): Promise<{ id: number; name: string }> {
// Simulate an async fetch
return new Promise(resolve =>
setTimeout(() => resolve({ id, name: 'Ada' }), 10),
);
}
(async () => {
const u = await getUser(1);
console.log(u);
})();
Try it Yourself »
Exercise
Wait for many promises in parallel with…
await Promise.
([p1, p2, p3]);
Three letters.
Discussion
Loading…