TypeScript Utility Types Guide — Partial, Pick, Omit and More

Learn TypeScript built-in utility types: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, and ReturnType with practical examples.

Built-In Utility Types Overview

TypeScript ships with utility types that perform common transformations. Key ones: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, ReturnType, Parameters.

Partial, Required, and Readonly

interface User {
  id: number
  name: string
  email: string
  bio?: string
}

type UserUpdate = Partial<User>
// All fields optional — ideal for PATCH requests

type UserRequired = Required<User>
// All fields required — strips optional flags

type ReadonlyUser = Readonly<User>
// All fields readonly — prevents mutation

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

Pick, Omit, and Record

interface Post {
  id: number; title: string; body: string
  authorId: number; createdAt: Date; publishedAt: Date | null
}

type PostSummary = Pick<Post, 'id' | 'title' | 'createdAt'>
// { id: number; title: string; createdAt: Date }

type PublicPost = Omit<Post, 'authorId'>
// All fields except authorId

type StatusMap = Record<'draft' | 'published' | 'archived', number>
const counts: StatusMap = { draft: 5, published: 23, archived: 12 }

ReturnType, Parameters, and Awaited

async function fetchUser(id: number): Promise<User> {
  return fetch(`/api/users/${id}`).then(r => r.json())
}

type FetchedUser = Awaited<ReturnType<typeof fetchUser>>
// User

type FetchParams = Parameters<typeof fetchUser>
// [id: number]

// Build a wrapper with the same signature
function withLogging<T extends (...args: any[]) => any>(fn: T) {
  return (...args: Parameters<T>): ReturnType<T> => {
    console.log(`Calling ${fn.name}`)
    return fn(...args)
  }
}

Frequently Asked Questions

What is the difference between Omit and Exclude?

Omit<T, K> removes keys from an object type. Exclude<T, U> removes members from a union type. They are different tools for different situations.

Can I combine utility types?

Yes. Partial<Pick<User, 'name' | 'email'>> creates a type with optional name and email. Deep utility types require custom recursive mapped types.