CodeOath
← All posts
TypeScript75 min total · 21 parts

TypeScript Fundamentals: Types, Interfaces, Generics, and Why It Catches Bugs Before Runtime

Contents — Part 13 of 21: Utility Types
Part 13 of 21 · ~2 min

Utility Types

TypeScript ships a set of built-in generic types that transform an existing type instead of redeclaring a near-duplicate by hand:

interface User { id: number; name: string; email: string; }

type PartialUser = Partial<User>;             // every field optional
type RequiredUser = Required<User>;           // every field required (opposite of Partial)
type ReadonlyUser = Readonly<User>;           // every field readonly
type UserPreview = Pick<User, "id" | "name">; // only id and name
type UserWithoutEmail = Omit<User, "email">;  // everything except email
type UserMap = Record<number, User>;          // { [id: number]: User }
type MaybeUser = User | undefined;
type DefiniteUser = NonNullable<MaybeUser>;   // strips undefined (and null) — back to User
UtilityWhat it does
Partial<T>Every property becomes optional — ideal for a "patch"-style update function's parameter
Required<T>Every property becomes required, even ones declared optional on T
Readonly<T>Every property becomes readonly — a compile-time-only immutability guard
Pick<T, K>A new type with only the listed keys
Omit<T, K>A new type with every key except the listed ones
Record<K, V>An object type mapping every key in K to a value of type V
ReturnType<F>Extracts a function type's return type, without calling it
Parameters<F>Extracts a function type's parameter types as a tuple
NonNullable<T>Removes null and undefined from a union

ReturnType and Parameters are especially useful for deriving a type from an existing function you don't control the source of (a third-party library, a generated client) instead of manually re-typing its signature:

function createUser(name: string, age: number) {
  return { id: Date.now(), name, age };
}

type NewUser = ReturnType<typeof createUser>; // { id: number; name: string; age: number }
type CreateUserArgs = Parameters<typeof createUser>; // [name: string, age: number]