Typing Promises & Async
Wrapping return values in the Promise<T> generic.
The async guarantee
In JavaScript, every function marked with the async keyword implicitly wraps its return value in a Promise.
Therefore, in TypeScript, the return type of any async function must always be Promise<T>, where T is the type of the value that will eventually be returned.
Preventing synchronous assumptions
If you forget to await an async function, you don't get the user data—you get a pending Promise object. TypeScript forces you to type it as Promise<User>, so if you try to access user.name without awaiting, the compiler will stop you.
Syntax
typescript
type User = { id: number; name: string };
// 1. Explicit return type: Promise<User>
async function fetchUser(): Promise<User> {
const response = await fetch("/api/user");
return response.json();
}
async function main() {
const userPromise = fetchUser();
// Error: Property 'name' does not exist on type 'Promise<User>'
// console.log(userPromise.name);
const user = await fetchUser();
// OK: user is now successfully unwrapped to 'User'
console.log(user.name);
}
Try it
Watch how a value is wrapped inside a Promise<T> box, and how the await keyword unpacks the box to retrieve the value T.
async function fetchUser(): Promise<User> { ... }
const pending = fetchUser();
const user = await pending;
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Every
asyncfunction must return aPromise<T>. - Awaiting a
Promise<T>unwraps it and gives youT. - If an async function returns nothing, use
Promise<void>. - Use the
Awaited<T>utility to extract the resolved type from a Promise.
Done with this concept?
Mark it complete to track your progress. No login needed.