TypeScript Utility Types You Should Know
Five essential built-in generic utility types in TypeScript that will save you hundreds of lines of code.
Tags
TypeScript Utility Types You Should Know
TL;DR
Nine built-in TypeScript utility types that replace hundreds of lines of redundant interface definitions. Stop manually rewriting types -- use Partial, Omit, Pick, Record, ReturnType, Readonly, Extract, Exclude, and NonNullable.
The Problem
You have a User type with ten properties. Now you need a type for update payloads (all optional), one for public profiles (no email/password), one for list views (just name and avatar). Without utility types, you write three nearly identical interfaces and keep them in sync manually.
The Solution
Partial -- Make all properties optional
Perfect for update/patch payloads where any subset of fields can be provided.
interface User {
id: string;
name: string;
email: string;
role: 'admin' | 'user';
}
// All properties become optional
type UpdateUserPayload = Partial<User>;
// { id?: string; name?: string; email?: string; role?: 'admin' | 'user' }
function updateUser(id: string, data: Partial<User>) {
// data can contain any combination of User fields
}Pick -- Select specific properties
Use when you want a few fields from a large type.
type UserPreview = Pick<User, 'id' | 'name'>;
// { id: string; name: string }Omit -- Remove specific properties
Use when you want everything except a few fields.
type PublicUser = Omit<User, 'email' | 'role'>;
// { id: string; name: string }
type CreateUserPayload = Omit<User, 'id'>; // ID is auto-generated
// { name: string; email: string; role: 'admin' | 'user' }Record -- Define key-value object types
Creates an object type with specific key and value types. Great for dictionaries and lookup maps.
type UserRoles = 'admin' | 'editor' | 'viewer';
type RolePermissions = Record<UserRoles, string[]>;
// { admin: string[]; editor: string[]; viewer: string[] }
const permissions: RolePermissions = {
admin: ['read', 'write', 'delete'],
editor: ['read', 'write'],
viewer: ['read'],
};ReturnType -- Extract a function's return type
Useful when you want to type a variable based on what a function returns, without manually duplicating the type.
function getConfig() {
return { apiUrl: 'https://api.example.com', timeout: 5000, retries: 3 };
}
type AppConfig = ReturnType<typeof getConfig>;
// { apiUrl: string; timeout: number; retries: number }Readonly -- Prevent mutations
Makes all properties read-only at the type level. Useful for config objects and state that should not be mutated directly.
type ImmutableUser = Readonly<User>;
const user: ImmutableUser = { id: '1', name: 'Ada', email: 'ada@test.com', role: 'admin' };
// user.name = 'Bob'; // Error: Cannot assign to 'name' because it is a read-only propertyExtract -- Pull matching members from a union
Extracts union members that are assignable to a given type.
type AllEvents = 'click' | 'scroll' | 'mouseover' | 'keydown' | 'keyup';
type MouseEvents = Extract<AllEvents, 'click' | 'mouseover' | 'scroll'>;
// 'click' | 'mouseover' | 'scroll'
// Practical: extract string-only types from a mixed union
type StringOrNumber = string | number | boolean;
type OnlyStrings = Extract<StringOrNumber, string>; // stringExclude -- Remove matching members from a union
The opposite of Extract -- removes specified members from a union.
type AllStatus = 'pending' | 'active' | 'suspended' | 'deleted';
type ActiveStatuses = Exclude<AllStatus, 'deleted' | 'suspended'>;
// 'pending' | 'active'NonNullable -- Strip null and undefined
Removes null and undefined from a type, useful when you have validated that a value exists.
type MaybeUser = User | null | undefined;
type DefiniteUser = NonNullable<MaybeUser>;
// User
function processUser(user: MaybeUser) {
if (!user) return;
const validUser: NonNullable<MaybeUser> = user; // Safe after null check
}Why This Works
These utility types are built into TypeScript -- no imports, no libraries. They compose together for powerful type transformations: Partial<Omit<User, 'id'>> gives you an optional-fields update payload without the ID. Readonly<Pick<User, 'id' | 'role'>> gives you an immutable subset. Instead of maintaining parallel type definitions that drift apart, you derive types from a single source of truth.
FAQ
What are TypeScript utility types?
Utility types are built-in generic types in TypeScript that transform existing types into new ones, such as making all properties optional (Partial) or extracting specific keys (Pick), saving you from writing redundant type definitions.
When should you use Omit vs Pick in TypeScript?
Use Pick when you want to select a few properties from a large type, and use Omit when you want to exclude a few properties from a large type. Pick is better when selecting fewer fields than you are excluding.
What does Record<K, T> do in TypeScript?
Record creates an object type where all keys are of type K and all values are of type T. For example, Record<string, number> defines an object with string keys and number values, useful for dictionaries and lookup maps.
Collaboration
Need help with a project?
Let's Build It
I help startups and established companies design, build, and scale world-class digital products. From deep technical architecture to pixel-perfect UI — let's bring your vision to life.
Related Articles
Generate Dynamic OG Images in Next.js
Generate dynamic Open Graph images in Next.js using the ImageResponse API with custom fonts, gradients, and data-driven content for social sharing.
GitHub Actions Reusable Workflows: Stop Repeating Yourself
Create reusable GitHub Actions workflows with inputs, secrets, and outputs to eliminate YAML duplication across repositories and teams efficiently.
Node.js Streams for Processing Large Files
Process large files efficiently in Node.js using readable, writable, and transform streams to avoid memory issues and handle data chunk by chunk.