Utility Types Overview
TypeScript ships with a rich library of built-in utility types — generic types that perform common type transformations. Instead of writing repetitive mapped types and conditional types by hand, you reach for the right utility type and move on.
This page gives you a complete map of every built-in utility type, grouped by category, so you know what is available and when to use it.
What Are Utility Types?
Utility types are generic type aliases defined in TypeScript's standard library (in lib.es5.d.ts and related files). They accept one or more type parameters and produce a new, transformed type. You use them the same way you use any generic type:
interface User {
id: number;
name: string;
email: string;
role: "admin" | "editor" | "viewer";
}
// Make every property optional
type PartialUser = Partial<User>;
// Make every property required (and non-optional)
type RequiredUser = Required<User>;
// Keep only selected properties
type UserPreview = Pick<User, "id" | "name">;
// Remove selected properties
type PublicUser = Omit<User, "email">;Object Manipulation Utilities
These utilities transform object types by adding, removing, or changing property modifiers.
Utility | What It Does | Example Result |
|---|---|---|
Partial<T> | Makes all properties optional | { id?: number; name?: string } |
Required<T> | Makes all properties required (removes ?) | { id: number; name: string } |
Readonly<T> | Makes all properties read-only | { readonly id: number } |
Pick<T, K> | Keeps only the listed keys | Pick<User, "id"> → { id: number } |
Omit<T, K> | Removes the listed keys | Omit<User, "email"> → no email prop |
Record<K, V> | Creates an object type with keys K and values V | Record<string, number> |
interface Product {
id: number;
name: string;
price: number;
stock: number;
}
// Only expose name and price to the client
type ProductCard = Pick<Product, "name" | "price">;
// Everything except stock for public APIs
type PublicProduct = Omit<Product, "stock">;
// A map from product IDs to products
type ProductMap = Record<number, Product>;
// All fields optional for PATCH requests
type ProductPatch = Partial<Product>;
// Snapshot that cannot be mutated
type FrozenProduct = Readonly<Product>;Type Extraction Utilities
These utilities extract or derive types from other types rather than transforming object shapes.
Utility | What It Extracts | Example |
|---|---|---|
ReturnType<T> | Return type of a function | ReturnType<() => string> → string |
Parameters<T> | Parameter types as a tuple | Parameters<(a: string) => void> → [string] |
InstanceType<T> | Instance type of a constructor | InstanceType<typeof Date> → Date |
ConstructorParameters<T> | Constructor param types as tuple | ConstructorParameters<typeof Date> |
Awaited<T> | Resolves Promise types recursively | Awaited<Promise<string>> → string |
function fetchUser(id: number): Promise<{ name: string; age: number }> {
return fetch(`/users/${id}`).then(r => r.json());
}
// Extract the resolved value type without duplicating it
type UserResponse = Awaited<ReturnType<typeof fetchUser>>;
// { name: string; age: number }
// Extract parameter types for testing / mocking
type FetchUserParams = Parameters<typeof fetchUser>;
// [id: number]
class EventEmitter {
constructor(public maxListeners: number) {}
}
type EmitterArgs = ConstructorParameters<typeof EventEmitter>;
// [maxListeners: number]Union Filtering Utilities
These utilities filter union types by keeping or removing members that match a condition.
Utility | What It Does | Example |
|---|---|---|
Extract<T, U> | Keeps members of T that are assignable to U | Extract<string | number | boolean, string | number> → string | number |
Exclude<T, U> | Removes members of T that are assignable to U | Exclude<string | null | undefined, null | undefined> → string |
NonNullable<T> | Removes null and undefined from T | NonNullable<string | null | undefined> → string |
type Status = "idle" | "loading" | "success" | "error";
// Keep only the non-terminal states
type ActiveStatus = Exclude<Status, "success" | "error">;
// "idle" | "loading"
// Keep only terminal states
type TerminalStatus = Extract<Status, "success" | "error">;
// "success" | "error"
type MaybeUser = { id: number } | null | undefined;
// Strip nullish types
type User = NonNullable<MaybeUser>;
// { id: number }String Manipulation Utilities
Introduced in TypeScript 4.1, these utility types operate on string literal types and are primarily useful with template literal types:
Utility | What It Does | Example |
|---|---|---|
Uppercase<S> | Converts string literal to uppercase | Uppercase<"hello"> → "HELLO" |
Lowercase<S> | Converts string literal to lowercase | Lowercase<"HELLO"> → "hello" |
Capitalize<S> | Uppercases the first character | Capitalize<"hello"> → "Hello" |
Uncapitalize<S> | Lowercases the first character | Uncapitalize<"Hello"> → "hello" |
type EventName = "click" | "focus" | "blur";
// Generate handler names: "onClick" | "onFocus" | "onBlur"
type Handler = `on${Capitalize<EventName>}`;
// Generate CSS class modifiers
type Modifier = "primary" | "secondary" | "danger";
type CSSClass = `btn--${Lowercase<Modifier>}`;
// "btn--primary" | "btn--secondary" | "btn--danger"
// Create getter method names from property names
type Getter<T extends string> = `get${Capitalize<T>}`;
type NameGetter = Getter<"name">; // "getName"How to Discover Utility Types
The best ways to explore TypeScript's built-in utility types:
In VS Code: type "Partial<" and trigger autocomplete — it shows the definition inline.
Visit the official TypeScript handbook page "Utility Types" for the authoritative list.
In any .ts file, Ctrl+click on a utility type name to jump to its definition in lib.es5.d.ts.
Run tsc --lib and examine the generated .d.ts files to see every built-in type.
The TypeScript playground at typescriptlang.org/play lets you hover over types to see their expansions.
When to Use vs Roll Your Own
Use built-in utility types when they match your need exactly. Roll your own when:
You need a deep version (e.g., DeepPartial, DeepReadonly) — built-ins are shallow.
You need to operate on specific nested paths rather than the whole object.
You need to compose multiple transformations into a named, reusable type.
Built-in behavior is close but not exact — write a custom mapped type instead of bending the built-in.
// Built-in: shallow partial
type ShallowPatch = Partial<{ a: { b: string } }>;
// { a?: { b: string } } — inner 'b' is still required
// Custom: deep partial
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
type DeepPatch = DeepPartial<{ a: { b: string } }>;
// { a?: { b?: string } } — inner 'b' is now optional tooCombining Utility Types
Utility types compose — pass one utility type result as the input to another:
interface Config {
host: string;
port?: number;
debug?: boolean;
secret: string;
}
// Remove secret, make everything optional, then freeze it
type SafeConfig = Readonly<Partial<Omit<Config, "secret">>>;
// { readonly host?: string; readonly port?: number; readonly debug?: boolean }
// A function that accepts any valid partial config (minus the secret)
function configure(options: SafeConfig): void {
console.log(options.host ?? "localhost");
}Omit, then Partial, then Readonly.Full Built-in Utility Types List
Category | Utility Types |
|---|---|
Object modifiers | Partial, Required, Readonly, Pick, Omit, Record |
Type extraction | ReturnType, Parameters, InstanceType, ConstructorParameters, Awaited |
Union filtering | Extract, Exclude, NonNullable |
String manipulation | Uppercase, Lowercase, Capitalize, Uncapitalize |
This types | ThisType, OmitThisParameter, ThisParameterType |
ThisType<T> are special markers used by the compiler, not transformations. They behave differently from object manipulation utilities.