Hint
Awaited recursively unwraps Promise<T>; NonNullable removes null and undefined from a type
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);
}
Awaited makes async code types much cleaner, especially with Promise.all and async utility functions.