DEV Community

Cover image for TypeScript Utility Types: A Complete Guide
Umesh Malik
Umesh Malik

Posted on • Originally published at umesh-malik.com

TypeScript Utility Types: A Complete Guide

TypeScript's built-in utility types are powerful tools that help you write cleaner, more maintainable code. In this guide, I'll walk through the most commonly used utility types with practical examples from real-world applications.

Why Utility Types Matter

When building large-scale applications like the ones I work on at Expedia Group, type safety isn't just nice to have — it's essential. Utility types help you derive new types from existing ones without duplication.

Partial<T>

Makes all properties of T optional. This is incredibly useful for update functions.

interface User {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'user';
}

function updateUser(id: string, updates: Partial<User>) {
  // Only update the fields that were provided
}

updateUser('123', { name: 'Umesh' }); // Valid!
Enter fullscreen mode Exit fullscreen mode

Required<T>

The opposite of Partial — makes all properties required.

interface Config {
  host?: string;
  port?: number;
  debug?: boolean;
}

const defaultConfig: Required<Config> = {
  host: 'localhost',
  port: 3000,
  debug: false,
};
Enter fullscreen mode Exit fullscreen mode

Pick<T, K>

Creates a type with only the specified properties.

type UserPreview = Pick<User, 'id' | 'name'>;

// Equivalent to:
// { id: string; name: string }
Enter fullscreen mode Exit fullscreen mode

Omit<T, K>

Creates a type excluding the specified properties.

type CreateUserInput = Omit<User, 'id'>;

// Everything except id
Enter fullscreen mode Exit fullscreen mode

Record<K, T>

Creates a type with keys of type K and values of type T.

type UserRoles = Record<string, User[]>;

const roleMap: UserRoles = {
  admin: [/* admin users */],
  editor: [/* editor users */],
};
Enter fullscreen mode Exit fullscreen mode

Practical Example: API Response Types

Here's how I combine these utility types in real projects:

interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

type UserListResponse = ApiResponse<Pick<User, 'id' | 'name' | 'role'>[]>;
type UserUpdatePayload = Partial<Omit<User, 'id'>>;
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Use Partial for update operations where not all fields are required
  • Use Pick and Omit to create focused types from larger interfaces
  • Use Record for dictionary-like structures
  • Combine utility types for complex transformations
  • These types are zero-cost at runtime — they only exist during compilation

Mastering these utility types will significantly improve your TypeScript code quality and developer experience.


Originally published at umesh-malik.com

Top comments (0)