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

`Awaited<T>` and `NonNullable<T>`

~7 min · utility-types, awaited, non-nullable, promises

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"Awaited unwraps Promises. NonNullable strips null and undefined. Two tiny utilities you'll use weekly."

Awaited<T> — recursively unwrap Promises

Awaited<Promise<string>> is string. Awaited<Promise<Promise<number>>> is also number — Awaited recurses until the value isn't a Promise anymore. This matches JavaScript's runtime: await Promise.resolve(Promise.resolve(x)) resolves to x, not Promise<x>.

Awaited was added in TypeScript 4.5 specifically because the older Promise<T> model couldn't accurately handle nested Promises. Anywhere you'd write ReturnType<typeof asyncFn>, you probably want to wrap it in Awaited to get the actually-resolved type.

NonNullable<T> — strip null and undefined

NonNullable<string | null | undefined> is string. The utility uses distribution over the union and removes any member that's null or undefined. Useful when you have a possibly-nullable type and want to assert (after a check) that it's now safe.

Awaited and NonNullable are surgical type strippers. They unwrap one wrapper at a time — Promise for the first, null/undefined for the second. Compose them with ReturnType to build the exact type you need from a function reference.

Code

Awaited and NonNullable·typescript
// Awaited — recursive Promise unwrap.
type A = Awaited<Promise<string>>;             // string
type B = Awaited<Promise<Promise<number>>>;    // number — recursive
type C = Awaited<string>;                       // string — pass-through

// The common chain: Awaited + ReturnType.
async function load(): Promise<User> { /* ... */ return {} as User }
type LoadedUser = Awaited<ReturnType<typeof load>>;   // User

// NonNullable — strip null and undefined.
type D = NonNullable<string | null>;            // string
type E = NonNullable<number | undefined>;       // number
type F = NonNullable<string | null | undefined>; // string

// Useful after a check.
function must<T>(v: T | null | undefined): NonNullable<T> {
  if (v === null || v === undefined) throw new Error('null');
  return v;
}

External links

Exercise

Given a function that may return Promise<User | null>, write a type for 'the non-null version of what it resolves to.' Confirm the type system catches the case where you forget to wrap with Awaited or NonNullable.
Hint
type SafeLoaded = NonNullable<Awaited<ReturnType<typeof load>>>. Order matters: Awaited first to unwrap Promise, then NonNullable to strip the null.

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.