Async/Await in TypeScript
Type precise async code with Promise<T>, async functions, and safe error handling.
Promise basics
function fetchJson(url: string): Promise<unknown> {
return fetch(url).then(r => r.json());
}
Annotate the resolved type when known:
interface User { id: number; name: string }
async function getUser(id: number): Promise<User> {
const r = await fetch(`/api/users/${id}`);
if (!r.ok) throw new Error("bad status");
return r.json() as Promise<User>;
}
async/await and error handling
async function run() {
try {
const u = await getUser(1);
console.log(u.name);
} catch (e: unknown) {
if (e instanceof Error) console.error(e.message);
}
}
Enable useUnknownInCatchVariables for safer catch typing.
Concurrency patterns
async function both(a: Promise<number>, b: Promise<number>) {
const [x, y] = await Promise.all([a, b]);
return x + y;
}
async function first<T>(ps: Promise<T>[]) {
return Promise.race(ps);
}
Prefer allSettled when each promise must be accounted for even on failures.
Top-level await
Supported in ESM. Configure module: ESNext and compatible bundler/Node. Exported types remain synchronous; be mindful in libraries.
Summary
- Type promises precisely; prefer
async/awaitwith try/catch - Use
Promise.allfor concurrency; considerallSettledvsrace - Configure ESM for top-level await where needed