C.W.K.
Stream
Lesson 01 of 05 · published

`Promise<T>`: The Typed Async Value

~9 min · async-promises, promise, generic

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"A Promise is a typed wrapper around a value that doesn't exist yet."

What Promise<T> describes

Promise<T> is a generic type that represents a value of type T that will be available later. The Promise has three states (pending, fulfilled, rejected); the type captures only the fulfilled value's type. Rejection is untyped — TypeScript can't predict what kind of error will be thrown.

You produce a Promise<T> via:

  • An async function (async function f(): Promise<User> { return getUser() })
  • new Promise<T>((resolve, reject) => ...)
  • Promise.resolve(value) or Promise.reject(error)
  • Library calls like fetch(), fs.readFile(), etc.

Consuming a Promise

Two ways: .then(callback) chains or await inside an async function. fetchUser().then(user => user.name) and const user = await fetchUser(); user.name are equivalent. The async/await form is generally preferred — it's flatter, easier to read, and integrates with try/catch.

The composition pattern

Async functions compose naturally. async function load(): Promise<Profile> can call other async functions, await them, and return a derived value. The Promise wrapper survives across all the steps; only at the topmost call do you unwrap it (with await or .then).

Promise<T> is the type of 'a future value of type T'. Reading async code as 'this is the type after you await' is the model that makes the rest of the track easy.

Code

Promise<T> — producing and consuming·typescript
// Promise<T> — the future value.
async function fetchUser(id: number): Promise<User> {
  const res = await fetch(`/users/${id}`);
  return res.json() as Promise<User>;  // res.json() is Promise<any>; we narrow
}

// Await — unwraps the Promise.
async function main() {
  const user = await fetchUser(1);     // user: User
  console.log(user.name);
}

// .then chain — same effect, older syntax.
fetchUser(1).then((user) => {
  console.log(user.name);              // user: User in the callback
});

// Promise.resolve and reject.
const ready: Promise<number> = Promise.resolve(42);
const failed: Promise<never> = Promise.reject(new Error('nope'));

External links

Exercise

Convert this .then chain to async/await: fetchUser(1).then(u => fetchPosts(u.id)).then(posts => posts.length). The async/await version should produce the same number.
Hint
const u = await fetchUser(1); const posts = await fetchPosts(u.id); return posts.length. Three lines, top to bottom, intermediate values named clearly.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.