MediumUtility Types📖 Theory Question

What are Awaited and NonNullable utility types?

💡

Hint

Awaited recursively unwraps Promise<T>; NonNullable removes null and undefined from a type

Full Answer

Awaited<T> — recursively unwraps the resolved type of a Promise (or thenable). Added in TypeScript 4.5.

type A = Awaited<Promise<string>>;
// string

type B = Awaited<Promise<Promise<number>>>;
// number (recursively unwrapped)

// Common pattern: get the type a fetch function resolves to
async function getUser(): Promise<User> { /* ... */ }

type ResolvedUser = Awaited<ReturnType<typeof getUser>>;
// User (not Promise<User>)

// Useful for typing the result of Promise.all
type MultiResult = Awaited<Promise<[User, Post[]]>>;
// [User, Post[]]

NonNullable<T> — removes null and undefined from a type:

type MaybeUser = User | null | undefined;

type DefiniteUser = NonNullable<MaybeUser>; // User

// Useful after null checks in generics
function assertDefined<T>(val: T): NonNullable<T> {
  if (val === null || val === undefined) {
    throw new Error('Value is null or undefined');
  }
  return val as NonNullable<T>;
}

// Filter nulls from an array
function compact<T>(arr: (T | null | undefined)[]): NonNullable<T>[] {
  return arr.filter((x): x is NonNullable<T> => x != null);
}
💡 Before TypeScript 4.5, getting the resolved type of a Promise required manual conditional types. Awaited makes async code types much cleaner, especially with Promise.all and async utility functions.

More Utility Types Questions

EasyWhat are Partial, Required, and Readonly utility types?EasyWhat are Pick and Omit utility types and when should you use them?EasyWhat is the Record utility type and when is it useful?EasyWhat are ReturnType, Parameters, and InstanceType utility types?

Practice this in a timed sprint →

5 free questions, no signup required

⚡ Start Sprint