TypeScript

Mastering Partial, Required, and Record in TypeScript: A Guide to Type Safety

TypeScript ships with utility types that reshape existing types. Three of the most useful: Partial, Required, and Record.

23 Apr 2024

Mastering Partial, Required, and Record in TypeScript: A Guide to Type Safety

TypeScript ships with utility types that reshape existing types. Three of the most useful: Partial, Required, and Record.

Partial — make everything optional

Say you have a User interface:

Text
interface User {
  name: string;
  age: number;
  email: string;
}

Now you need an update function that accepts any subset of these fields. Partial makes every property optional:

Text
type PartialUser = Partial<User>;

PartialUser has the same properties as User, but none of them are required. Perfect for PATCH-style updates where you only send what changed.

Required — make everything mandatory

Got a type where some fields are optional? Required forces them all to be present:

Text
type RequiredUser = Required<PartialUser>;

This reverses Partial. Every field must be provided. Useful at validation boundaries where you need a fully-formed object before saving.

Record — typed key-value maps

Record creates a type where keys map to a specific value type:

Text
type NumberRecord = Record<string, number>;

const numberRecord: NumberRecord = {
  'one': 1,
  'two': 2,
  'three': 3,
};

Think of it as a typed dictionary. Instead of { [key: string]: number }, you get a cleaner declaration that scales better in complex types.

The trade-off

These utilities reduce boilerplate and catch bugs at compile time. But overusing them creates types that are hard to read. If you're nesting Partial<Required<Pick<User, 'name'>>>, you've gone too far. Extract a named type instead.