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:
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:
type NewUser = {
[K in 'name' | 'mobile']: string;
};
// This is equivalent to:
type NewUser = {
name: string;
mobile: string;
}Combined with keyof:
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:
/**
* 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:
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:
/**
* Make all properties in T optional
*/
type Partial<T> = {
[P in keyof T]?: T[P];
};Usage:
type User = {
name: string;
mobile: string;
}
type NewUser = Partial<User>;
// Equivalent to:
type NewUser = {
name?: string;
mobile?: string;
}Combined with Record:
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:
/**
* Make all properties in T readonly
*/
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};Usage:
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:
/**
* 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:
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.
