Utility Types Reference
TypeScript ships with a set of global utility types that transform existing types into new ones. They cover the most common type manipulation patterns so you don't have to reinvent them. This page documents every built-in utility type with its signature, what it does, and a realistic example.
Overview
Utility Type | Signature | One-line summary |
|---|---|---|
Partial | Partial<T> | All properties become optional |
Required | Required<T> | All properties become required |
Readonly | Readonly<T> | All properties become readonly |
Record | Record<K, V> | Object type with keys K and values V |
Pick | Pick<T, K> | Keeps only the listed keys |
Omit | Omit<T, K> | Removes the listed keys |
Exclude | Exclude<T, U> | Removes union members assignable to U |
Extract | Extract<T, U> | Keeps only union members assignable to U |
NonNullable | NonNullable<T> | Removes null and undefined |
ReturnType | ReturnType<F> | Return type of a function |
Parameters | Parameters<F> | Parameter types as a tuple |
ConstructorParameters | ConstructorParameters<C> | Constructor parameter types |
InstanceType | InstanceType<C> | Instance type of a constructor |
ThisType | ThisType<T> | Sets type of this inside object literal methods |
Awaited | Awaited<T> | Recursively unwraps Promise types |
NoInfer | NoInfer<T> | Prevents inference at the site (TS 5.4+) |
OmitThisParameter | OmitThisParameter<F> | Removes this parameter from function type |
Uppercase | Uppercase<S> | Converts string literal to uppercase |
Lowercase | Lowercase<S> | Converts string literal to lowercase |
Capitalize | Capitalize<S> | Uppercases first character |
Uncapitalize | Uncapitalize<S> | Lowercases first character |
Partial<T>
Signature: type Partial<T> = { [P in keyof T]?: T[P] }
Makes all properties of T optional. Useful for update/patch operations where you only provide the fields you want to change.
interface User {
id: number;
name: string;
email: string;
age: number;
}
// All fields required — you must provide everything
const fullUser: User = { id: 1, name: 'Alice', email: 'alice@example.com', age: 30 };
// Partial — provide only what you want to update
function updateUser(id: number, changes: Partial<User>): User {
const existing = getUserById(id);
return { ...existing, ...changes };
}
updateUser(1, { name: 'Alicia' }); // OK
updateUser(1, { email: 'new@example.com' }); // OK
updateUser(1, { age: 31, name: 'Alicia' }); // OK
// Real-world: form state where fields are filled in gradually
type UserFormState = Partial<User>;
const formState: UserFormState = {}; // valid — all optionalRequired<T>
Signature: type Required<T> = { [P in keyof T]-?: T[P] }
Makes all properties of T required, removing all optional markers. The opposite of Partial.
interface Config {
host?: string;
port?: number;
debug?: boolean;
}
// Required<Config> — all fields must be provided
type StrictConfig = Required<Config>;
// { host: string; port: number; debug: boolean }
// Useful for validating that a config has been fully resolved
function startServer(config: StrictConfig) {
console.log(`Starting on ${config.host}:${config.port}`);
}
const defaults: Config = { host: 'localhost', port: 3000, debug: false };
const resolved = defaults as Required<Config>;
startServer(resolved); // OKReadonly<T>
Signature: type Readonly<T> = { readonly [P in keyof T]: T[P] }
Makes all properties of T readonly. The object can be created normally but cannot be mutated afterward.
interface Point {
x: number;
y: number;
}
const origin: Readonly<Point> = { x: 0, y: 0 };
// origin.x = 5; // Error: Cannot assign to 'x' because it is a read-only property.
// Useful for configuration objects, constants, and immutable state
type ImmutableUser = Readonly<User>;
// Note: Readonly is shallow — nested objects are still mutable
interface Tree {
value: number;
children: Tree[];
}
const tree: Readonly<Tree> = { value: 1, children: [] };
tree.children.push({ value: 2, children: [] }); // Still works! Readonly is shallow.
// For deep immutability, use a recursive utility type or libraries like immerReadonly is shallow. It makes the direct properties readonly but nested objects remain mutable. For deep immutability, you need a recursive utility or a library.Record<K, V>
Signature: type Record<K extends keyof any, T> = { [P in K]: T }
Creates an object type with keys of type K and values of type V. The cleanest way to type a dictionary/map object.
// Simple dictionary
const cache: Record<string, unknown> = {};
// Typed dictionary with union key
type Country = 'US' | 'UK' | 'CA';
type CurrencyMap = Record<Country, string>;
const currencies: CurrencyMap = {
US: 'USD',
UK: 'GBP',
CA: 'CAD',
};
// Missing 'CA' would be a type error
// Index-based lookup table
type HttpStatusMap = Record<number, string>;
const statusMessages: HttpStatusMap = {
200: 'OK',
404: 'Not Found',
500: 'Internal Server Error',
};
// Nested Record
type Matrix = Record<string, Record<string, number>>;
// Record is equivalent to an index signature with a union key
// { [K in Country]: string } is the same as Record<Country, string>Pick<T, K>
Signature: type Pick<T, K extends keyof T> = { [P in K]: T[P] }
Constructs a type by picking a set of properties K from type T. Use it to create sub-types or slimmed-down views of larger types.
interface User {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
}
// Only expose safe public fields
type PublicUser = Pick<User, 'id' | 'name' | 'email'>;
// { id: number; name: string; email: string }
// Pick for form types
type UserRegistrationForm = Pick<User, 'name' | 'email' | 'password'>;
// Works with function props too
interface ButtonProps {
onClick: () => void;
disabled?: boolean;
label: string;
variant: 'primary' | 'secondary';
size: 'sm' | 'md' | 'lg';
}
type MinimalButtonProps = Pick<ButtonProps, 'onClick' | 'label'>;Omit<T, K>
Signature: type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
Constructs a type by removing properties K from type T. The inverse of Pick — use it when it's easier to say what you don't want.
interface User {
id: number;
name: string;
email: string;
password: string;
createdAt: Date;
}
// Remove sensitive fields for public API response
type SafeUser = Omit<User, 'password'>;
// { id: number; name: string; email: string; createdAt: Date }
// Remove auto-generated fields for creation payloads
type CreateUserPayload = Omit<User, 'id' | 'createdAt'>;
// { name: string; email: string; password: string }
// Useful when you want most fields but a few should change type
type UserUpdate = Omit<User, 'id' | 'createdAt'> & {
id?: number; // make id optional for updates
};Pick when there are few properties you want to keep. Use Omit when there are few properties you want to remove. The result is the same — choose the cleaner expression.Exclude<T, U>
Signature: type Exclude<T, U> = T extends U ? never : T
From a union type T, removes all members that are assignable to U. Works on unions, not object types.
type AllStatus = 'active' | 'inactive' | 'pending' | 'deleted'; // Remove 'deleted' from the usable statuses type ActiveStatus = Exclude<AllStatus, 'deleted'>; // 'active' | 'inactive' | 'pending' // Remove multiple members type VisibleStatus = Exclude<AllStatus, 'deleted' | 'inactive'>; // 'active' | 'pending' // Remove primitive types from a union type OnlyStrings = Exclude<string | number | boolean, number | boolean>; // string // Exclude is used internally to implement Omit // Omit<T, K> = Pick<T, Exclude<keyof T, K>> // Useful for narrowing event handler types type MouseEvents = 'click' | 'dblclick' | 'mousedown' | 'mouseup'; type ClickEvents = Exclude<MouseEvents, 'mousedown' | 'mouseup'>; // 'click' | 'dblclick'
Extract<T, U>
Signature: type Extract<T, U> = T extends U ? T : never
From a union type T, keeps only the members that are assignable to U. The inverse of Exclude.
type Mixed = string | number | boolean | null | undefined;
// Keep only the falsy types
type Falsy = Extract<Mixed, null | undefined | false | 0 | ''>;
// null | undefined (false/0/'' are not in Mixed)
// Extract only string or number types
type Primitives = Extract<Mixed, string | number>;
// string | number
// Extract discriminated union members
type Action =
| { type: 'fetch'; url: string }
| { type: 'save'; data: unknown }
| { type: 'delete'; id: number };
type FetchAction = Extract<Action, { type: 'fetch' }>;
// { type: 'fetch'; url: string }
type MutatingActions = Extract<Action, { type: 'save' | 'delete' }>;
// { type: 'save'; data: unknown } | { type: 'delete'; id: number }NonNullable<T>
Signature: type NonNullable<T> = T & {}
Removes null and undefined from type T. Use it when you've already performed a null check and want to reflect that in the type.
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>; // string
// Practical use: after filtering out nulls
function compact<T>(arr: (T | null | undefined)[]): NonNullable<T>[] {
return arr.filter((x): x is NonNullable<T> => x != null);
}
const items = ['Alice', null, 'Bob', undefined, 'Charlie'];
const names = compact(items); // string[]
// Useful with mapped types to remove nullability from all fields
type DeNullified<T> = {
[K in keyof T]: NonNullable<T[K]>;
};ReturnType<F>
Signature: type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Extracts the return type of a function type. Extremely useful when working with functions whose return types are complex or inferred.
function createUser(name: string, age: number) {
return { id: Math.random(), name, age, createdAt: new Date() };
}
// Instead of duplicating the return type definition:
type CreatedUser = ReturnType<typeof createUser>;
// { id: number; name: string; age: number; createdAt: Date }
// Works great with factory functions
function makeStore() {
return {
count: 0,
increment() { this.count++; },
decrement() { this.count--; },
};
}
type Store = ReturnType<typeof makeStore>;
// Works with async functions
async function fetchUser(id: number) {
const response = await fetch(`/api/users/${id}`);
return response.json() as Promise<{ id: number; name: string }>;
}
type FetchUserResult = Awaited<ReturnType<typeof fetchUser>>;
// { id: number; name: string }Parameters<F>
Signature: type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never
Extracts the parameter types of a function as a tuple. Useful for wrapping functions or building higher-order utilities.
function createUser(name: string, age: number, email: string): void {}
type CreateUserParams = Parameters<typeof createUser>;
// [name: string, age: number, email: string]
// Access individual parameters
type NameParam = Parameters<typeof createUser>[0]; // string
type AgeParam = Parameters<typeof createUser>[1]; // number
// Use case: creating a memoize wrapper
function memoize<T extends (...args: unknown[]) => unknown>(fn: T) {
const cache = new Map<string, ReturnType<T>>();
return (...args: Parameters<T>): ReturnType<T> => {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key) as ReturnType<T>;
const result = fn(...args) as ReturnType<T>;
cache.set(key, result);
return result;
};
}
// Spread parameters from a tuple
type Fn = (a: string, b: number) => boolean;
type FnArgs = Parameters<Fn>; // [string, number]
declare function callWith(fn: Fn, args: FnArgs): boolean;ConstructorParameters<C>
Signature: type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never
Extracts the parameter types of a class constructor as a tuple. Mirrors Parameters but for constructors.
class HttpClient {
constructor(
private baseUrl: string,
private timeout: number = 5000,
private headers: Record<string, string> = {}
) {}
}
type HttpClientArgs = ConstructorParameters<typeof HttpClient>;
// [baseUrl: string, timeout?: number, headers?: Record<string, string>]
// Use case: factory that forwards constructor args
function createWithLogging<T extends new (...args: unknown[]) => unknown>(
Cls: T,
...args: ConstructorParameters<T>
): InstanceType<T> {
console.log(`Creating ${Cls.name}`);
return new Cls(...args) as InstanceType<T>;
}
const client = createWithLogging(HttpClient, 'https://api.example.com');InstanceType<C>
Signature: type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any
Extracts the instance type of a constructor function or class. Useful when you have a reference to a class (not an instance) and need to type what it produces.
class Database {
query(sql: string): unknown[] { return []; }
close(): void {}
}
type DbInstance = InstanceType<typeof Database>;
// Database (the instance type, same as the class name in simple cases)
// More useful with generic factory patterns
function instantiate<T extends new (...args: unknown[]) => unknown>(
Cls: T
): InstanceType<T> {
return new Cls() as InstanceType<T>;
}
const db = instantiate(Database); // type: Database
// Useful for class registries / dependency injection
type Constructor<T = unknown> = new (...args: unknown[]) => T;
const registry = new Map<string, Constructor>();
registry.set('db', Database);
function resolve<T extends Constructor>(key: string): InstanceType<T> {
const Cls = registry.get(key) as T;
return new Cls() as InstanceType<T>;
}ThisType<T>
Signature: interface ThisType<T> {}
A marker interface used in object literal methods to specify the type of this. Unlike other utility types, ThisType doesn't transform the type — it annotates the context. Requires the noImplicitThis compiler option.
interface PluginMethods {
greet(): void;
farewell(): void;
}
interface Plugin {
name: string;
methods: PluginMethods & ThisType<{ name: string } & PluginMethods>;
}
const plugin: Plugin = {
name: 'MyPlugin',
methods: {
greet() {
console.log(`Hello from ${this.name}`); // 'this' is typed
},
farewell() {
console.log(`Goodbye from ${this.name}`);
},
},
};
// ThisType is most commonly seen in framework/library internal code
// like Vue 2's Options API or Vuex's action contextAwaited<T>
Signature: type Awaited<T> = T extends null | undefined ? T : T extends object & { then(onfulfilled: infer F, ...): any } ? ...infer V... : T
Recursively unwraps the resolved value of a Promise. Works with nested promises too. Introduced in TypeScript 4.5.
// Basic usage
type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<number>>>; // number (nested unwrap)
type C = Awaited<string>; // string (non-promise passthrough)
type D = Awaited<Promise<string | null>>; // string | null
// Practical: extract resolved type from async functions
async function fetchUsers() {
return [{ id: 1, name: 'Alice' }];
}
type Users = Awaited<ReturnType<typeof fetchUsers>>;
// { id: number; name: string }[]
// Useful in generic async utilities
async function withTimeout<T>(
promise: Promise<T>,
ms: number
): Promise<T> {
const timeout = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
);
return Promise.race([promise, timeout]);
}
type TimeoutResult<P extends Promise<unknown>> = Awaited<P>;NoInfer<T> (TypeScript 5.4+)
Signature: type NoInfer<T> = intrinsic
Prevents TypeScript from inferring the type parameter T from a particular argument site. Useful when you want inference to happen from one specific argument and not others.
// Problem: TypeScript infers T from both arguments
function createState<T>(initial: T, fallback: T): T {
return initial ?? fallback;
}
// This infers T as string | number (from both args)
const state = createState('hello', 42); // T = string | number
// With NoInfer: T is inferred only from 'initial'
// 'fallback' must be assignable to T but doesn't drive inference
function createStateSafe<T>(initial: T, fallback: NoInfer<T>): T {
return initial ?? fallback;
}
// Now T = string (inferred from first arg), and 42 is a type error
// createStateSafe('hello', 42); // Error: 42 not assignable to string
// Practical use: default values in generic functions
function getOrDefault<T>(value: T | undefined, defaultValue: NoInfer<T>): T {
return value !== undefined ? value : defaultValue;
}OmitThisParameter<F>
Signature: type OmitThisParameter<T> = unknown extends ThisParameterType<T> ? T : T extends (...args: infer A) => infer R ? (...args: A) => R : T
Removes the this parameter from a function type. Useful when binding a method and wanting the type to reflect that this is no longer free.
interface User {
name: string;
greet(this: User): string;
}
type BoundGreet = OmitThisParameter<User['greet']>;
// () => string (this parameter removed)
// Practical use: binding methods
const user: User = {
name: 'Alice',
greet() { return `Hello, I am ${this.name}`; },
};
const boundGreet: BoundGreet = user.greet.bind(user);
boundGreet(); // OK — no 'this' needed anymoreIntrinsic String Manipulation Types
TypeScript includes four intrinsic (built-in compiler-level) types for manipulating string literal types.
Type | Input | Output |
|---|---|---|
Uppercase<S> | 'hello' | 'HELLO' |
Lowercase<S> | 'HELLO' | 'hello' |
Capitalize<S> | 'hello' | 'Hello' |
Uncapitalize<S> | 'Hello' | 'hello' |
type A = Uppercase<'hello'>; // 'HELLO'
type B = Lowercase<'WORLD'>; // 'world'
type C = Capitalize<'alice'>; // 'Alice'
type D = Uncapitalize<'Alice'>; // 'alice'
// Most useful in template literal types and mapped types
type EventKey<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventKey<'click'>; // 'onClick'
type FocusEvent = EventKey<'focus'>; // 'onFocus'
// Building a full event handler object type
type Events = 'click' | 'focus' | 'blur' | 'change';
type EventHandlers = {
[K in Events as `on${Capitalize<K>}`]: (event: Event) => void;
};
// { onClick: ..., onFocus: ..., onBlur: ..., onChange: ... }
// Uppercase over union distributes
type UpperEvents = Uppercase<Events>;
// 'CLICK' | 'FOCUS' | 'BLUR' | 'CHANGE'Combining Utility Types
Utility types become most powerful when composed together.
interface User {
id: number;
name: string;
email: string;
password: string;
role: 'admin' | 'user';
createdAt: Date;
}
// Public view: no password, readonly
type PublicUser = Readonly<Omit<User, 'password'>>;
// Create payload: no auto-generated fields
type CreateUser = Omit<User, 'id' | 'createdAt'>;
// Update payload: all fields optional except id
type UpdateUser = Partial<Omit<User, 'id'>> & Pick<User, 'id'>;
// Admin-only view: extra admin fields
type AdminUserView = Required<PublicUser> & { lastLoginAt: Date };
// Only string-valued fields
type StringFields<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
type UserStringFields = StringFields<User>;
// { name: string; email: string; password: string; role: string }
// Deep partial (recursive utility)
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};Partial, Required, Pick, Omit, and Record already covers what you need.