Notifications

No notifications

Utility types are TypeScript's standard library of type-level helpers. Instead of copy-pasting modified versions of an interface, you compose them: Partial, Pick, ReturnType. Master the dozen most common ones and you'll cut your type code in half.

On this page

Detailed Theory

Why utility types?

Imagine an API. You have a full User:

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

You want a "partial update" payload (PATCH /user). You could write a second interface — or use Partial:

type UserPatch = Partial<User>; // every field optional

That's the spirit. Below are the ones you'll use weekly.

Object-shape helpers

Partial — make every field optional

type UserPatch = Partial<User>;
// { id?: number; name?: string; email?: string; createdAt?: Date }

Required — make every field required

Useful after Partial to "lock in" a defaults-merged object:

type Settings = { theme?: string; fontSize?: number };
function withDefaults(s: Settings): Required<Settings> { /* … */ }

Readonly — make every field readonly

type FrozenUser = Readonly<User>;
const f: FrozenUser = { /* … */ };
// f.name = "x"; // ❌

Pick — keep only certain keys

type UserCard = Pick<User, "id" | "name">;
// { id: number; name: string }

Omit — drop certain keys

type UserPublic = Omit<User, "email">;
// { id: number; name: string; createdAt: Date }

Pick and Omit together are the workhorses of any DTO layer.

Record — build an object map

type StatusCount = Record<"loading" 
"success"
"error", number>; // { loading: number; success: number; error: number }

type Dict = Record<string, number>; // open-ended

Union helpers

Exclude — remove members

type T = "a" 
"b"
"c"; type Without = Exclude<T, "b">; // "a"
"c"

Extract — keep matching members

type Only = Extract<T, "a"
"z">; // "a"

NonNullable — drop null & undefined

type Maybe = string
null
undefined; type S = NonNullable<Maybe>; // string

Function helpers

Parameters — tuple of arg types

function fetchUser(id: number, opts: { cache?: boolean }) { return null; }
type Args = Parameters<typeof fetchUser>;
// [number, { cache?: boolean }]

ReturnType — return type

type R = ReturnType<typeof fetchUser>; // null  (whatever it returns)

function loadUser() { return { id: 1, name: "Ada" }; } type User = ReturnType<typeof loadUser>; // { id: number; name: string }

This is the "infer the type from the implementation" trick — perfect when types live in code, not interfaces.

ConstructorParameters & InstanceType

class Box<T> { constructor(public value: T) {} }
type CParams = ConstructorParameters<typeof Box<string>>; // [string]
type Inst = InstanceType<typeof Box<string>>;             // Box<string>

Promise helpers

Awaited — unwrap Promises (recursively)

type A = Awaited<Promise<string>>;            // string
type B = Awaited<Promise<Promise<number>>>;   // number

Pair with ReturnType for "what does this async function actually resolve to":

async function getUser() { return { id: 1 }; }
type User = Awaited<ReturnType<typeof getUser>>; // { id: number }

String helpers (intrinsic)

type U = Uppercase<"hello">;       // "HELLO"
type L = Lowercase<"WORLD">;       // "world"
type C = Capitalize<"foo bar">;    // "Foo bar"
type UC = Uncapitalize<"Foo">;     // "foo"

Combine with template literal types for handler-name generation, route building, etc.

Composing them

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

// Public profile = User without password, every field readonly type PublicProfile = Readonly<Omit<User, "password">>;

// Form = every field optional except id type UserForm = Partial<User> & Pick<User, "id">;

Build your own

Most utility types are simple mapped types under the hood:

type MyPartial<T> = { [K in keyof T]?: T[K] };
type MyReadonly<T> = { readonly [K in keyof T]: T[K] };
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };

Once these click, mapped/conditional types in Phase 4 will feel obvious.

Cheat sheet

WantUse
Make all fields optionalPartial
Make all fields requiredRequired
Make all fields immutableReadonly
Keep only some keysPick
Drop some keysOmit
Build a mapRecord
Remove union membersExclude
Keep union membersExtract
Strip null/undefinedNonNullable
Get function's argsParameters
Get function's returnReturnType
Unwrap promiseAwaited