DTTooleras

TypeScript Utility Types: A Complete Guide with Examples

Master TypeScript utility types — Partial, Required, Pick, Omit, Record, Exclude, Extract, ReturnType, and more. Every built-in utility type explained with practical examples.

DevToolsHub Team20 min read1,331 words

What Are Utility Types?

TypeScript provides a set of built-in utility types that help you transform and manipulate types. They're generic types that take one or more type parameters and return a new type. Think of them as functions, but for types instead of values.

Utility types are essential for writing DRY, maintainable TypeScript code. Instead of duplicating type definitions, you can derive new types from existing ones.

Partial<T>

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;
// }

// Perfect for update functions where you only send changed fields
function updateUser(id: number, updates: Partial<User>) {
  // updates can have any subset of User properties
}

updateUser(1, { name: "Alice" });           // ✅
updateUser(1, { email: "a@b.com", age: 30 }); // ✅
updateUser(1, {});                           // ✅

Required<T>

The opposite of Partial — makes all properties required:

interface Config {
  host?: string;
  port?: number;
  debug?: boolean;
}

type RequiredConfig = Required<Config>;
// {
//   host: string;
//   port: number;
//   debug: boolean;
// }

// Useful for ensuring all config values are set after merging defaults
function createServer(config: RequiredConfig) {
  // All properties guaranteed to exist
  console.log(`Starting on ${config.host}:${config.port}`);
}

Readonly<T>

Makes all properties read-only (cannot be reassigned):

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

type ReadonlyUser = Readonly<User>;

const user: ReadonlyUser = { id: 1, name: "Alice" };
user.name = "Bob"; // ❌ Error: Cannot assign to 'name' because it is a read-only property

// Great for function parameters that shouldn't be mutated
function processUser(user: Readonly<User>) {
  // Can read user.name, but can't modify it
  console.log(user.name);
}

Pick<T, K>

Creates a type with only the specified properties from T:

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

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

// Perfect for API responses that shouldn't include sensitive data
function getPublicProfile(user: User): PublicUser {
  return {
    id: user.id,
    name: user.name,
    email: user.email,
  };
}

Omit<T, K>

The opposite of Pick — creates a type with all properties except the specified ones:

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

// Create a type for new user input (no id or createdAt)
type CreateUserInput = Omit<User, "id" | "createdAt">;
// {
//   name: string;
//   email: string;
//   password: string;
// }

Record<K, T>

Creates a type with keys of type K and values of type T:

// String keys, number values
type Scores = Record<string, number>;
const scores: Scores = {
  alice: 95,
  bob: 87,
  charlie: 92,
};

// Union keys
type Status = "pending" | "active" | "inactive";
type StatusLabels = Record<Status, string>;
const labels: StatusLabels = {
  pending: "Pending Review",
  active: "Active",
  inactive: "Deactivated",
};

// Complex values
type UserMap = Record<string, User>;
const users: UserMap = {
  "user-1": { id: 1, name: "Alice", email: "a@b.com", password: "...", createdAt: new Date() },
};

// Useful for lookup tables, dictionaries, and maps
type HttpMethods = "GET" | "POST" | "PUT" | "DELETE";
type RouteHandlers = Record<HttpMethods, (req: Request) => Response>;

Exclude<T, U>

Removes types from a union that are assignable to U:

type AllStatus = "pending" | "active" | "inactive" | "deleted";
type ActiveStatus = Exclude<AllStatus, "deleted">;
// "pending" | "active" | "inactive"

type NonNullable = Exclude<string | number | null | undefined, null | undefined>;
// string | number

// Remove specific types from a union
type Primitive = string | number | boolean | null | undefined;
type NonNullPrimitive = Exclude<Primitive, null | undefined>;
// string | number | boolean

Extract<T, U>

The opposite of Exclude — keeps only types assignable to U:

type AllTypes = string | number | boolean | (() => void);
type FunctionTypes = Extract<AllTypes, Function>;
// () => void

type StringOrNumber = Extract<string | number | boolean, string | number>;
// string | number

NonNullable<T>

Removes null and undefined from a type:

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

// Useful with optional chaining results
function getUser(id: number): User | null {
  // ...
}

type DefiniteUser = NonNullable<ReturnType<typeof getUser>>;
// User

ReturnType<T>

Extracts the return type of a function:

function createUser(name: string, email: string) {
  return {
    id: Math.random(),
    name,
    email,
    createdAt: new Date(),
  };
}

type CreatedUser = ReturnType<typeof createUser>;
// {
//   id: number;
//   name: string;
//   email: string;
//   createdAt: Date;
// }

// Useful when you don't want to define a separate interface
// The function IS the source of truth for the type

Parameters<T>

Extracts the parameter types of a function as a tuple:

function greet(name: string, age: number, isAdmin: boolean) {
  // ...
}

type GreetParams = Parameters<typeof greet>;
// [string, number, boolean]

// Access individual parameters
type FirstParam = Parameters<typeof greet>[0]; // string
type SecondParam = Parameters<typeof greet>[1]; // number

// Useful for wrapper functions
function logAndCall<T extends (...args: unknown[]) => unknown>(
  fn: T,
  ...args: Parameters<T>
): ReturnType<T> {
  console.log("Calling with:", args);
  return fn(...args) as ReturnType<T>;
}

Awaited<T>

Unwraps the type inside a Promise:

type PromiseString = Promise<string>;
type Resolved = Awaited<PromiseString>;
// string

// Works with nested promises too
type NestedPromise = Promise<Promise<number>>;
type DeepResolved = Awaited<NestedPromise>;
// number

// Useful with async function return types
async function fetchUser(id: number): Promise<User> {
  // ...
}

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

Combining Utility Types

The real power comes from combining them:

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  role: "admin" | "user" | "moderator";
  createdAt: Date;
  updatedAt: Date;
}

// API response (no password, no timestamps)
type UserResponse = Omit<User, "password" | "createdAt" | "updatedAt">;

// Create input (no id, no timestamps)
type CreateUserInput = Omit<User, "id" | "createdAt" | "updatedAt">;

// Update input (partial, no id or timestamps)
type UpdateUserInput = Partial<Omit<User, "id" | "createdAt" | "updatedAt">>;

// Admin-only fields
type AdminUser = Pick<User, "id" | "name" | "email" | "role">;

// Read-only user for display
type DisplayUser = Readonly<Pick<User, "id" | "name" | "email">>;

// User lookup map
type UserMap = Record<string, Readonly<UserResponse>>;

Custom Utility Types

You can build your own:

// Make specific properties optional
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

type UserWithOptionalEmail = PartialBy<User, "email">;
// email is optional, everything else required

// Make specific properties required
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;

// Deep partial (recursive)
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

// Mutable (remove readonly)
type Mutable<T> = {
  -readonly [P in keyof T]: T[P];
};

// Nullable
type Nullable<T> = {
  [P in keyof T]: T[P] | null;
};

Quick Reference

UtilityPurposeExample
Partial<T>All properties optionalUpdate functions
Required<T>All properties requiredConfig validation
Readonly<T>All properties read-onlyImmutable data
Pick<T, K>Keep specific propertiesAPI responses
Omit<T, K>Remove specific propertiesHide sensitive fields
Record<K, T>Create key-value typeLookup tables
Exclude<T, U>Remove from unionFilter status types
Extract<T, U>Keep from unionExtract function types
NonNullable<T>Remove null/undefinedStrict types
ReturnType<T>Get function return typeInfer types
Parameters<T>Get function paramsWrapper functions
Awaited<T>Unwrap PromiseAsync return types
typescriptutility typestypescript typespartialpickomitrecordtypescript guide

Related articles

All articles

Practice with free tools

200+ free developer tools that run in your browser.

Browse all tools →