Skip to main content

Utility Types

Utility types are built-in generic types that transform other types, so a related type is derived instead of written by hand and stays in sync with the original. The most commonly used:

  • for objects: Partial, Required, Readonly, Pick, Omit, Record;
  • for unions: Exclude, Extract, NonNullable;
  • for functions and promises: ReturnType, Parameters, Awaited.

Most of them are ordinary types written with mapped and conditional types; a few, such as NoInfer and the string helpers, are built into the compiler.

Applies to: TypeScript 7.0.

Details​

Objects​

TypeWhat it doesTypical use
Partial<T>all properties optionalupdate payloads, options with defaults
Required<T>all properties required (removes ?)config after defaults are applied
Readonly<T>all properties readonlyprops, state, values that must not change
Pick<T, K>only the keys K; K must be keys of Ta smaller view of a type
Omit<T, K>all keys except K; K is not checkedinput types without id or server fields
Record<K, V>an object with keys K and values Vdictionaries, a lookup by every union member
  • Partial and Readonly are shallow: nested objects keep their types.
  • Readonly is compile-time only. At runtime the object can still be changed; use Object.freeze for that.
  • Record<'a' | 'b', V> requires every key. For a dictionary with any string key, Record<string, V> returns V on access, not V | undefined, unless noUncheckedIndexedAccess is on.

Unions​

TypeWhat it doesExample
Exclude<U, E>removes members of U assignable to EExclude<'a' | 'b' | 'c', 'a'> → 'b' | 'c'
Extract<U, E>keeps members of U assignable to EExtract<string | number, number> → number
NonNullable<T>removes null and undefinedNonNullable<string | null> → string

Pick and Omit work on keys of an object; Exclude and Extract work on members of a union.

Functions and Promises​

TypeWhat it does
ReturnType<F>the return type of a function type
Parameters<F>the parameter types as a tuple
Awaited<T>the value of a promise, unwrapped recursively
ConstructorParameters<C>the parameters of a class constructor
InstanceType<C>the type of an instance of a class
NoInfer<T>blocks inference from this position (TypeScript 5.4)
  • They take a type, so a function value needs typeof: ReturnType<typeof fetchUser>.
  • Awaited<ReturnType<typeof fetchUser>> is the type of the data an async function resolves to.
  • String helpers (Uppercase, Capitalize and others) are described in Type Operators.

Example​

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

type CreateUserInput = Omit<User, 'id' | 'createdAt'>; // name, email
type UpdateUserInput = Pick<User, 'id'> & Partial<CreateUserInput>;
type UserPreview = Pick<User, 'id' | 'name'>;

type Role = 'admin' | 'editor' | 'viewer';
const permissions: Record<Role, string[]> = {
admin: ['read', 'write', 'delete'],
editor: ['read', 'write'],
viewer: ['read'],
}; // a missing role is a compile error

async function fetchUser(id: number) {
return { id, name: 'Ann' };
}

type FetchUserArgs = Parameters<typeof fetchUser>; // [id: number]
type FetchedUser = Awaited<ReturnType<typeof fetchUser>>; // { id: number; name: string }

// NoInfer: the default must be one of the options, not widen them
function pick<T extends string>(options: T[], fallback: NoInfer<T>) {
return options[0] ?? fallback;
}

pick(['s', 'm', 'l'], 'm');
pick(['s', 'm', 'l'], 'xl'); // Error: Argument of type '"xl"' is not assignable to parameter of type '"l" | "m" | "s"'.
Pitfalls of Omit
interface User {
id: number;
name: string;
}

// A wrong key in Omit is not an error: K is not checked against the keys
type WithoutName = Omit<User, 'fullName'>; // still has `name`

// Omit on a union is not distributive: it keeps only the common keys
type Shape =
| { kind: 'circle'; radius: number; color: string }
| { kind: 'square'; size: number; color: string };

type Uncolored = Omit<Shape, 'color'>; // { kind: 'circle' | 'square' }

const c: Uncolored = { kind: 'circle', radius: 1 }; // Error: Object literal may only specify known properties, and 'radius' does not exist in type 'Uncolored'.

// A distributive version applies Omit to each member
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown
? Omit<T, K>
: never;

const ok: DistributiveOmit<Shape, 'color'> = { kind: 'circle', radius: 1 };

Follow-up Questions​

  • How is Partial implemented? { [K in keyof T]?: T[K] }, a mapped type; see Type Operators.
  • What is the difference between Omit and Exclude? Omit removes keys from an object type; Exclude removes members from a union. Omit is built on Pick and Exclude.
  • How do you make a deep Partial? A recursive mapped type: { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K] }. Functions and arrays need special cases, so libraries like type-fest are often used.
  • How do you get the type of a component's props? ComponentProps<typeof Button>; see Typing React.

Common Mistakes​

  • ReturnType<fetchUser> instead of ReturnType<typeof fetchUser>.
  • Expecting Readonly to freeze an object at runtime, or to be deep.
  • Using Omit on a discriminated union and losing the members.
  • Partial<User> for a form that needs some fields: it makes every field optional, including the required ones.

See Also​