TypeScript’s utility types are one of the most powerful features of the language, yet many developers only scratch the surface. In this article, we’ll explore how built-in utility types like Partial can make your code cleaner, safer, and more expressive.
The problem: rigid types
Imagine you have a User type where every field is required:
type User = {
name: string;
age: number;
address: string;
}
This works great when creating a new user — you want all fields present. But what about updating a user? You might only want to change the name, leaving age and address untouched. Passing a full User object just to update one field feels wrong.
Enter Partial
TypeScript’s Partial<T> utility type creates a new type where all properties become optional:
type PartialUser = Partial<User>;
// Now this is perfectly valid:
const user1: PartialUser = {
name: "Alice"
}
Under the hood, Partial<User> is equivalent to:
type PartialUser = {
name?: string;
age?: number;
address?: string;
}
This is incredibly useful for update functions:
function updateUser(id: string, updates: Partial<User>): User {
const existing = getUserById(id);
return { ...existing, ...updates };
}
// Only update what you need
updateUser("123", { name: "Bob" });
updateUser("456", { age: 30, address: "123 Main St" });
Beyond Partial: other utility types worth knowing
TypeScript ships with several utility types that solve common patterns:
Required<T>— the opposite ofPartial, makes all properties requiredPick<T, K>— creates a type with only the specified keysOmit<T, K>— creates a type excluding the specified keysReadonly<T>— makes all properties read-only
// Only name and age
type UserPreview = Pick<User, "name" | "age">;
// Everything except address
type UserWithoutAddress = Omit<User, "address">;
// Immutable user
type FrozenUser = Readonly<User>;
When to use utility types
Utility types shine when you need variations of the same shape without duplicating definitions. Instead of maintaining parallel types that drift apart over time, derive them from a single source of truth.
The rule of thumb: if you’re copying a type and tweaking a few fields, there’s probably a utility type that does it better.