Skip to content

TypeScript ships built-in advanced types for everyday use, but books, documentation, and online articles don't always explain them clearly. This article is a reference for anyone who needs the basics laid out.

Prerequisite: keyof ​

Before understanding advanced types, you need to understand keyof:

typescript
interface User {
  name: string;
  mobile: string;
}

type keys = keyof User; // Equivalent to: type keys = 'name' | 'mobile'

keyof extracts an interface's keys. Understanding keyof is essential for the advanced types that follow: Record and Pick.

Prerequisite: Mapped Types ​

Mapped types allow you to quickly create types:

typescript
type NewUser = {
  [K in 'name' | 'mobile']: string;
};

// This is equivalent to:
type NewUser = {
  name: string;
  mobile: string;
}

Combined with keyof:

typescript
interface User {
  name: string;
  mobile: string;
}

type NewUser = {
  [K in keyof User]: string;
};

Now that the prerequisites are covered, let's move on to TypeScript's advanced types.

Record Type ​

Record is widely used — it lets you quickly create a type. Let's look at its source code:

typescript
/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

It's straightforward. Combined with the prerequisites:

typescript
type User = Record<'name' | 'mobile', string>;

// This is equivalent to:
type User = {
  name: string;
  mobile: string;
}

Partial Type ​

The Partial type makes all properties of a type optional. Source code:

typescript
/**
 * Make all properties in T optional
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};

Usage:

typescript
type User = {
  name: string;
  mobile: string;
}

type NewUser = Partial<User>;

// Equivalent to:
type NewUser = {
  name?: string;
  mobile?: string;
}

Combined with Record:

typescript
type NewUser = Partial<Record<'name' | 'mobile', string>>;

Readonly Type ​

As the name suggests, Readonly makes all properties of the passed type read-only. Source code:

typescript
/**
 * Make all properties in T readonly
 */
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

Usage:

typescript
type User = Readonly<Record<'name' | 'mobile', string>>;

// Equivalent to:
type User = {
  readonly name: string;
  readonly mobile: string;
}

Pick Type ​

Pick selects specific properties from a type and returns a new type. Source code:

typescript
/**
 * From T, pick a set of properties whose keys are in the union K
 */
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

Usage:

typescript
type User = {
  name: string;
  mobile: string;
  address: string;
}

type NewUser = Pick<User, 'name' | 'mobile'>;

// Equivalent to:
type NewUser = {
  name: string;
  mobile: string;
}

Summary ​

These advanced types were introduced by TypeScript back in 2016 and have been widely adopted in packages and frameworks. They're quite useful day to day, so I've noted them here.