TypeScript Utility Types

TypeScript provides a set of built-in utility types that help you transform and manipulate existing types. These utilities are essential for creating flexible and reusable type definitions.

Built-in Utility Types

Partial

Makes all properties of T optional.

interface User {
  id: number;
  name: string;
  email: string;
  age: number;
}

type PartialUser = Partial<User>;
// Equivalent to:
// {
//   id?: number;
//   name?: string;
//   email?: string;
//   age?: number;
// }

// Usage
function updateUser(id: number, updates: Partial<User>) {
  return { id, ...updates };
}

updateUser(1, { name: 'John' }); // OK
updateUser(1, { name: 'John', age: 30 }); // OK

Required

Makes all properties of T required.

interface Config {
  apiUrl?: string;
  timeout?: number;
  retries?: number;
}

type RequiredConfig = Required<Config>;

function createClient(config: RequiredConfig) {
  return {
    url: config.apiUrl,
    timeout: config.timeout,
    retries: config.retries
  };
}

Readonly

Makes all properties of T readonly.

interface MutableUser {
  id: number;
  name: string;
  email: string;
}

type ReadonlyUser = Readonly<MutableUser>;

const user: ReadonlyUser = { id: 1, name: 'John', email: 'john@example.com' };
// user.name = 'Jane'; // Error: Cannot assign to 'name' because it is a read-only property

Pick<T, K>

Selects specific properties from T.

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  createdAt: Date;
  updatedAt: Date;
}

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

function getUserPublicInfo(user: User): UserPublicInfo {
  return {
    id: user.id,
    name: user.name,
    email: user.email
  };
}

Omit<T, K>

Excludes specific properties from T.

type UserWithoutPassword = Omit<User, 'password'>;

function createUser(userData: Omit<User, 'id' | 'createdAt' | 'updatedAt'>) {
  return {
    ...userData,
    id: Math.random(),
    createdAt: new Date(),
    updatedAt: new Date()
  };
}

Record<K, V>

Creates an object type with keys of type K and values of type V.

type Status = 'pending' | 'approved' | 'rejected';
type StatusMessages = Record<Status, string>;

const messages: StatusMessages = {
  pending: 'Your request is being processed',
  approved: 'Your request has been approved',
  rejected: 'Your request has been rejected'
};

Exclude<T, U>

Excludes types from T that are assignable to U.

type AllColors = 'red' | 'green' | 'blue' | 'yellow' | 'purple';
type PrimaryColors = 'red' | 'green' | 'blue';
type SecondaryColors = Exclude<AllColors, PrimaryColors>; // 'yellow' | 'purple'

Extract<T, U>

Extracts types from T that are assignable to U.

type WarmColors = 'red' | 'yellow' | 'orange';
type AvailableWarmColors = Extract<AllColors, WarmColors>; // 'red' | 'yellow'

NonNullable

Excludes null and undefined from T.

type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>; // string

Parameters

Extracts the parameter types of a function type T.

function createUser(name: string, age: number, email: string) {
  return { name, age, email };
}
type CreateUserParams = Parameters<typeof createUser>; // [string, number, string]

ReturnType

Extracts the return type of a function type T.

function getUser() {
  return { id: 1, name: 'John', email: 'john@example.com' };
}
type User = ReturnType<typeof getUser>;

Advanced Utility Types

Custom Utility Types

type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

Conditional Utility Types

type Awaited<T> = T extends Promise<infer U> ? U : T;
type IsFunction<T> = T extends (...args: any[]) => any ? true : false;
type FirstParameter<T> = T extends (first: infer P, ...args: any[]) => any ? P : never;

Key Concepts

  1. Type Transformation: Utility types transform existing types
  2. Composability: Utility types can be combined and nested
  3. Generic Constraints: Using extends to constrain type parameters
  4. Conditional Types: Using extends and infer for type logic
  5. Template Literal Types: For string manipulation (TypeScript 4.1+)

Common Interview Questions

  • What's the difference between Pick and Omit?
  • How would you create a deep partial type?
  • What's the purpose of Record<K, V>?
  • How do you extract function parameter types?
  • What's the difference between Exclude and Extract?

Related Topics

  • Type vs Interface
  • Generics
  • Conditional Types
  • Template Literal Types
  • Mapped Types