Skip to Content
Course content
Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you've ordered a high-end espresso machine online. When you hit "Buy," the store doesn't immediately hand you the machine; they hand you a tracking number. That tracking number is a promise that, eventually, you'll get your machine. But sometimes, things get weird. The tracking number leads you to a shipping coordinator, who then gives you a *different* tracking number from a local courier, who finally delivers the actual box to your door.

In your head, you aren't thinking, "I possess a promise of a promise of an espresso machine." You're thinking, "I'm getting an espresso machine." You've mentally stripped away all the "delivery" layers to focus on the actual object at the center.

That is exactly what Awaited<T> does for your types. While the await keyword unwraps a promise at runtime, the Awaited utility type unwraps a promise at compile-time.

Unwrapping the Promise Onion

If you have a simple promise, Awaited is pretty straightforward. It looks at the type and says, "If this is a promise, give me what's inside. If it's not a promise, just leave it alone."

type Delivery = Promise<string>;
type Result = Awaited<Delivery>; // Result is now just 'string'

type SimpleValue = number;
type StillSimple = Awaited<SimpleValue>; // StillSimple is still 'number'

Now, you might be thinking, "Why not just use Promise<string> and access the generic?" Because real-world APIs are messy. Sometimes you encounter "thenables" or nested promises (promises that resolve to other promises). Awaited is recursive. It will keep digging through the layers until it hits a non-promise value.

Handling Recursive Nesting

I've seen this happen in legacy codebases where a wrapper function accidentally wraps a result in multiple promises. If you tried to manually define the return type, you'd be writing Promise<Promise<Promise<User>>>, which is a nightmare to maintain. Awaited flattens all of that instantly.

type DeepPromise = Promise<Promise<Promise<string>>>;

// This recursively unwraps everything
type FinalValue = Awaited<DeepPromise>; // FinalValue is 'string'

Connecting Awaited to Function Return Types

The most common place you'll actually use this is when you're working with generic functions and you want to create a second function that handles the result of the first one. You don't want to hardcode the return type because the first function might change.

Check this out:

async function fetchUserConfig() {
  // Imagine some complex logic here
  return { theme: 'dark', notifications: true };
}

// We use 'ReturnType' to get the Promise, then 'Awaited' to get the actual object
type UserConfig = Awaited<ReturnType<typeof fetchUserConfig>>;

function applyConfig(config: UserConfig) {
  console.log(`Setting theme to ${config.theme}`);
}

By chaining Awaited and ReturnType, your applyConfig function is now automatically synced with whatever fetchUserConfig returns. If you add a language property to the config in the fetcher, UserConfig updates automatically. I love this pattern because it eliminates the need to manually maintain duplicate interface definitions for API responses.




📋 Practical Task

Synchronizing a Cached API Response Type

You are building a caching layer for a weather application. You have a function that fetches weather data, which might be returned from a cache (already resolved) or an API (a promise). You need to create a WeatherDisplay component that accepts the unwrapped data type.

Your Task:

  1. Given the function getWeatherData, use ReturnType and Awaited to create a type called WeatherData.
  2. Apply that WeatherData type to the data parameter in the renderWeather function.
async function getWeatherData() {
  return {
    temp: 72,
    condition: 'Sunny',
    humidity: 45
  };
}

// 1. Extract the unwrapped return type here
type WeatherData = // Your code here

function renderWeather(data: WeatherData) {
  console.log(`The weather is ${data.condition} at ${data.temp} degrees.`);
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.