TypeScript Utility Types: Beyond the Basics
TypeScript's built-in utility types let you transform types without rewriting them. Instead of creating UserUpdate manually with all optional fields, use Partial<User>. They're composable, powerful, and once you learn them, you'll use them everywhere.
The Essential Ones
interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'user';
createdAt: Date;
}Partial<T> — makes all properties optional:
// All fields become optional
type UserUpdate = Partial<User>;
// { id?: number; name?: string; email?: string; ... }
function updateUser(id: number, data: Partial<User>) {
// Can pass { name: 'New Name' } without other fields
}Required<T> — makes all properties required (opposite of Partial):
interface Config {
host?: string;
port?: number;
debug?: boolean;
}
type StrictConfig = Required<Config>;
// { host: string; port: number; debug: boolean; }Pick<T, K> — select specific properties:
type UserPreview = Pick<User, 'id' | 'name'>;
// { id: number; name: string; }
// Great for API response types
type LoginResponse = Pick<User, 'id' | 'email' | 'role'>;Omit<T, K> — remove specific properties:
type CreateUserInput = Omit<User, 'id' | 'createdAt'>;
// { name: string; email: string; role: 'admin' | 'user'; }
// Use for forms where some fields are auto-generatedRecord<K, V> — create an object type with specific key and value types:
type UserRoles = Record<string, 'admin' | 'user' | 'guest'>;
// { [key: string]: 'admin' | 'user' | 'guest'; }
// Typed dictionaries
const permissions: Record<User['role'], string[]> = {
admin: ['read', 'write', 'delete'],
user: ['read'],
};String Manipulation Types
type Upper = Uppercase<'hello'>; // 'HELLO'
type Lower = Lowercase<'HELLO'>; // 'hello'
type Cap = Capitalize<'hello'>; // 'Hello'
type Uncap = Uncapitalize<'Hello'>; // 'hello'Advanced Combinations
// Make only some fields optional
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type UserWithOptionalEmail = PartialBy<User, 'email'>;
// Make only some fields required
type RequiredBy<T, K extends keyof T> = T & Required<Pick<T, K>>;
// Readonly version for immutable state
type ImmutableUser = Readonly<User>;
// Extract function return type
function getUser() { return { id: 1, name: 'Alice' }; }
type UserResult = ReturnType<typeof getUser>;
// { id: number; name: string; }
// Extract function parameters
type GetUserParams = Parameters<typeof getUser>;
// []Real-World Patterns
// API endpoint types
interface ApiEndpoints {
'/users': { GET: User[]; POST: Omit<User, 'id'>; };
'/users/:id': { GET: User; PUT: Partial<User>; DELETE: void; };
}
// Event handler map
type EventMap = Record<string, (...args: any[]) => void>;
// Component props with defaults
type PropsWithDefaults<P, D extends Partial<P>> = Omit<P, keyof D> & Partial<D>;Format your TypeScript: JavaScript/TypeScript Formatter — paste code, get formatted output instantly.