TypeScript Utility Types (Part 4)

Introduction

In Part 3, we explored Generics in TypeScript and how they help build reusable, type-safe abstractions. In this part, we’ll focus on one of the most practical and frequently used features in real-world TypeScript projects:

Utility Types

TypeScript utility types help you transform existing types instead of rewriting them, making your code more concise, maintainable, and expressive.

In this article, we’ll cover the most commonly used utility types:

  • Partial
  • Pick
  • Omit
  • Record

What Are Utility Types?

Utility types are built-in generic types provided by TypeScript that allow you to manipulate and derive new types from existing ones.

They are heavily used in:

  • API models
  • Form handling
  • State management
  • Component props
  • Backend DTOs

Base Example (Used Across All Examples)

interface User {
  id: number;
  name: string;
  email: string;
  isActive: boolean;
}

Partial

What It Does

Partial<T> makes all properties optional.

Syntax

type PartialUser = Partial<User>;

Resulting Type

{
  id?: number;
  name?: string;
  email?: string;
  isActive?: boolean;
}

Real-World Use Case: Update API Payload

function updateUser(id: number, data: Partial<User>) {
  // send PATCH request
}

updateUser(1, { name: "Nishank" });

✅ Ideal for PATCH requests and partial updates


Pick<T, K>

What It Does

Pick<T, K> creates a type by selecting specific properties from an existing type.

Syntax

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

Resulting Type

{
  id: number;
  name: string;
}

Real-World Use Case: Lightweight API Response

function getUserList(): UserPreview[] {
  return [{ id: 1, name: "Nishank" }];
}

✅ Reduces payload size and improves clarity


Omit<T, K>

What It Does

Omit<T, K> creates a new type by excluding specific properties.

Syntax

type UserWithoutEmail = Omit<User, "email">;

Resulting Type

{
  id: number;
  name: string;
  isActive: boolean;
}

Real-World Use Case: Public API Response

function getPublicUser(): UserWithoutEmail {
  return {
    id: 1,
    name: "Nishank",
    isActive: true,
  };
}

✅ Prevents leaking sensitive data


Record<K, T>

What It Does

Record<K, T> creates an object type where:

  • Keys are of type K
  • Values are of type T

Syntax

type RolePermissions = Record<string, boolean>;

Resulting Type

{
  [key: string]: boolean;
}

Real-World Use Case 1: Permission Map

type Permissions = Record<"read" | "write" | "delete", boolean>;

const userPermissions: Permissions = {
  read: true,
  write: false,
  delete: false,
};

Real-World Use Case 2: Dynamic Lookup Table

type UserMap = Record<number, User>;

const users: UserMap = {
  1: { id: 1, name: "Nishank", email: "n@test.com", isActive: true },
};

Combining Utility Types

Utility types can be composed together.

Example: Editable User

type EditableUser = Partial<Omit<User, "id">>;

✅ Commonly used in forms


Utility Types – Quick Comparison

Utility TypePurposeCommon Use Case
PartialMake all fields optionalPATCH / update forms
PickSelect specific fieldsList / preview views
OmitExclude fieldsPublic / safe APIs
RecordKey-value mappingPermissions, lookups

Best Practices

  • Prefer utility types over redefining interfaces
  • Combine utility types with generics for flexibility
  • Use Pick and Omit to control API contracts
  • Keep types DRY and reusable

Conclusion

TypeScript utility types are essential tools for writing clean, maintainable, and scalable applications.

By mastering Partial, Pick, Omit, and Record, you can:

  • Avoid duplication
  • Enforce strong typing
  • Improve API design
  • Write safer application logic

In the next part, you can explore Advanced Utility Types and Conditional Types.


Happy coding!

You might also like