Utility Types

Intermediate
TypeScript

Partial, Pick, Omit, Record, ReturnType and friends. Deriving types from other types is what keeps them in sync when the source changes.

Overview

The habit that separates comfortable TypeScript from tedious TypeScript is deriving rather than duplicating. If a form edits a subset of User, that form's type should be computed from User, so that renaming a field breaks the form at compile time instead of quietly diverging. The built-in utility types cover almost every derivation you need day to day, and knowing the list well is more valuable than being able to write exotic conditional types.

The Ones You Use Daily

Modifying and selecting from an existing object type.

Partial, Pick, Omit, Record
interface User {
  id: number
  name: string
  email: string
  role: 'student' | 'admin'
}

Partial<User>              // every field optional — PATCH payloads
Required<User>             // every field required
Readonly<User>             // every field readonly

Pick<User, 'id' | 'name'>          // { id, name }
Omit<User, 'id'>                   // everything except id — creation payloads

Record<'easy' | 'hard', number>    // { easy: number; hard: number }

// Realistic use
type CreateUser = Omit<User, 'id'>
type UpdateUser = Partial<Omit<User, 'id'>>
type UserCard   = Pick<User, 'name' | 'role'>

// Rename a field on User and every one of these updates with it.
// Hand-written duplicates would silently drift.

Unions and Functions

Filtering unions, and extracting types out of functions and promises.

ReturnType, Awaited, and typeof
type Status = 'idle' | 'loading' | 'success' | 'error'

Exclude<Status, 'idle'>            // 'loading' | 'success' | 'error'
Extract<Status, 'success' | 'error'>   // 'success' | 'error'
NonNullable<string | null>         // string

// Extracting from functions — very useful for inferred sources
function getConfig() { return { retries: 3, timeout: 5000 } }
type Config = ReturnType<typeof getConfig>     // { retries: number; timeout: number }

type Args = Parameters<typeof getConfig>
type Resolved = Awaited<ReturnType<typeof fetchUser>>   // unwraps the Promise

// typeof on a value gives its type — the bridge between the two worlds
const DEFAULTS = { page: 1, size: 20 } as const
type Defaults = typeof DEFAULTS        // { readonly page: 1; readonly size: 20 }
type DefaultKey = keyof typeof DEFAULTS   // 'page' | 'size'

as const

Freezes a literal into its narrowest type. It is how you turn a constant array into a union.

One array, used as data and as a type
const levels = ['easy', 'medium', 'hard']
// type: string[] — the literals are lost

const levels2 = ['easy', 'medium', 'hard'] as const
// type: readonly ['easy', 'medium', 'hard']

type Level = typeof levels2[number]    // 'easy' | 'medium' | 'hard'

// One source of truth for both the runtime list and the type:
levels2.forEach(...)                   // iterate at runtime
function setLevel(l: Level) { }        // and the union is derived from it

// This replaces the enum for most cases, and unlike an enum it
// compiles to nothing extra and interops cleanly with plain JSON.

Key Points to Remember

  • 1Derive types from a single source rather than duplicating shapes — renames then break at compile time
  • 2Partial, Pick, Omit and Record cover most everyday derivations; Omit<User, "id"> is the creation payload
  • 3ReturnType, Parameters and Awaited extract types out of existing functions and promises
  • 4typeof on a value yields its type, bridging the value world and the type world
  • 5as const preserves literals, and typeof arr[number] turns a constant array into a union — usually better than an enum

Interview Questions

Sign in to ask Aria
1

How would you type the payload for creating a user when you already have a User interface?

Easy
2

What does `as const` do, and how do you derive a union type from a constant array?

Medium
3

Why derive types with Pick and Omit instead of writing the shapes out?

Medium

Ask Aria about Utility Types

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…