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

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:
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:
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:
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:
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.