TypeScript Async Programming
TypeScript types every asynchronous value as a Promise<T>, letting the compiler track what a pending operation will eventually resolve to.
Typing Promises
A `Promise<T>` represents a value of type `T` that isn't available yet. Whatever you pass to `resolve` inside the promise executor must match `T`, and anything you get back from `.then()` is typed as `T` as well, so the compiler catches mismatches long before the promise ever settles.
A Basic Typed Promise
function fetchUser(id: number): Promise<{ id: number; name: string }> {
return new Promise((resolve) => {
setTimeout(() => resolve({ id, name: "Ada Lovelace" }), 100);
});
}
fetchUser(1).then((user) => console.log(user.name));async/await and Inferred Return Types
A function marked `async` always returns a `Promise`, even if you write a plain `return` inside it - TypeScript wraps the return type for you. Inside the function, `await` unwraps a `Promise<T>` down to `T`, and a `try`/`catch` around it lets you handle rejected promises the same way you'd handle a thrown synchronous error.
async/await with Error Handling
function fetchUser(id: number): Promise<{ id: number; name: string }> {
return Promise.resolve({ id, name: "Grace Hopper" });
}
async function loadUserName(id: number): Promise<string> {
try {
const user = await fetchUser(id);
return user.name;
} catch (error) {
console.error("Failed to load user", error);
return "unknown";
}
}
loadUserName(2).then((name) => console.log(name));Running Promises in Parallel
Awaiting promises one after another runs them sequentially, which wastes time when the operations don't depend on each other. `Promise.all` starts every promise at once and, in TypeScript, infers a typed tuple that matches the exact type of each input promise once they all resolve.
Promise.all with a Typed Tuple
function fetchUser(id: number): Promise<{ id: number; name: string }> {
return Promise.resolve({ id, name: "Linus" });
}
function fetchPosts(userId: number): Promise<string[]> {
return Promise.resolve(["Hello world", "TypeScript tips"]);
}
async function loadDashboard(userId: number): Promise<void> {
const [user, posts] = await Promise.all([fetchUser(userId), fetchPosts(userId)]);
console.log(user.name, posts.length);
}
loadDashboard(1);- Promise.all - waits for every promise, rejects as soon as one rejects
- Promise.allSettled - waits for every promise and never rejects
- Promise.race - settles as soon as the first promise settles
- Promise.any - resolves as soon as the first promise fulfills
Exercise: TypeScript Async Programming
What does an async function always return, regardless of what its body returns?