Utility Types

TypeScript's standard library (lib.es5.d.ts) defines utility types with the operators of this section: Partial is a mapped type, Exclude a conditional type, NoInfer a compiler intrinsic. Learn them before writing your own:

The most used utility types and the TypeScript version that added them
Utility Result Since
Partial<T>, Required<T> All keys optional, required 2.1, 2.8
Readonly<T> Top-level keys readonly 2.1
Record<K, V> Keys K, values V 2.1
Pick<T, K>, Omit<T, K> Keep keys K, drop keys K 2.1, 3.5
Exclude<U, M> Union minus members of M 2.8
NonNullable<T> Drops null, undefined 2.8
ReturnType<F> A function's return type 2.8
Parameters<F> A function's parameter tuple 3.1
Awaited<T> Unwrapped promise result 4.5
NoInfer<T> Blocks inference here 5.4
Deriving request types from one modelCSS
interface User { id: number; name: string; email: string; role: "admin" | "member" }
type NewUser = Omit<User, "id">;                         // a signup form's payload
type UserPatch = Partial<Pick<User, "name" | "email">>;  // { name?: string; email?: string }
const roleLabels: Record<User["role"], string> = { admin: "Administrator", member: "Member" };
declare function updateUser(id: number, patch: UserPatch): Promise<User>;
type Updated = Awaited<ReturnType<typeof updateUser>>;   // User
function choose<T extends string>(sizes: T[], fallback: NoInfer<T>): T {
  return sizes[0] ?? fallback;
}
const draft: NewUser = { id: 7, name: "Ada", email: "ada@example.com", role: "admin" };
updateUser(1, { role: "admin" });
choose(["sm", "md", "lg"], "xl");
Output
users.ts(10,26): error TS2353: Object literal may only specify known properties, and 'id' does
  not exist in type 'NewUser'.
users.ts(11,17): error TS2353: Object literal may only specify known properties, and 'role'
  does not exist in type 'Partial<Pick<User, "email" | "name">>'.
users.ts(12,28): error TS2345: Argument of type '"xl"' is not assignable to parameter of type
  '"lg" | "md" | "sm"'.

Without NoInfer, TypeScript would also infer T from "xl" and accept it. Record<User["role"], string> forces a label for every role, so adding "guest" to User breaks the build until roleLabels is updated.