How to Use Async/Await in TypeScript
Use async/await in TypeScript when code needs to wait for promises in a readable, synchronous-looking flow. This is perfect for API calls, database requests, file operations, and sequential async workflows.
What you’ll build or solve
You’ll learn how to use async and await in TypeScript with typed promise returns, error handling, and reusable async helpers. You’ll also know how to keep async flows type-safe.
Learn TypeScript on Mimo
When this approach works best
This approach is the right choice when multiple async steps should stay readable and easy to debug.
Common real-world scenarios include:
- API requests
- Database queries
- File reads
- Auth token refresh
- Sequential workflows
This is a bad idea when many async tasks can safely run in parallel.
Prerequisites
You only need:
- Basic TypeScript functions
- Familiarity with promises
- Understanding of
try/catch
Step-by-step instructions
Step 1: Create an async function
Use the async keyword before the function.
async function getUser(): Promise<string> {
return "Alex";
}
Even plain return values become promises automatically.
This makes the return type Promise<string>.
Step 2: Wait for async values with await
Use await inside another async function.
async function showUser(): Promise<void> {
const user = await getUser();
console.log(user);
}
This pauses execution until the promise resolves.
The resolved type stays fully inferred.
Step 3: Add error handling
Wrap awaited logic in try/catch.
async function loadProfile(): Promise<void> {
try {
const response = await fetch("/api/profile");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Failed to load profile");
}
}
This is the cleanest production-ready pattern.
Step 4: Use typed async arrow functions
The same pattern works with arrows.
const getScore = async (): Promise<number> => {
return 95;
};
What to look for:
asyncwraps the return in a promiseawaitunwraps resolved values- Great for readable async flows
- Use
try/catchfor failures - Keep promise return types explicit
Examples you can copy
API fetch
const response = await fetch("/api/users");
Typed async helper
const loadCount = async (): Promise<number> => 10;
Sequential workflow
await refreshToken();
await loadUser();
Common mistakes and how to fix them
Mistake 1: Using await outside async functions
What the reader might do:
const user = await getUser();
Why it breaks: await requires async context.
Corrected approach:
Wrap it in an async function.
Mistake 2: Forgetting the promise return type
What the reader might do:
async function getUser(): string
Why it breaks: async functions always return promises.
Corrected approach:
Use Promise<string>.
Mistake 3: Serializing independent async work
What the reader might do:
Await many unrelated requests one by one.
Why it breaks: performance slows unnecessarily.
Corrected approach:
Use Promise.all().
Troubleshooting
If await errors, make sure the function is async.
If the return type mismatches, wrap it in Promise<T>.
If performance is slow, parallelize safe tasks.
If failures disappear silently, add try/catch.
Quick recap
- Use
asyncfor promise-returning functions - Use
awaitfor readable async flow - Return
Promise<T> - Add
try/catchfor failures - Use
Promise.all()for parallel safe tasks
Join 35M+ people learning for free on Mimo
4.8 out of 5 across 1M+ reviews
Check us out on Apple AppStore, Google Play Store, and Trustpilot