TypeScript provides built-in advanced types to assist in daily development, but whether in books or documentation, the explanations aren't always clear, and online articles can be hard to digest. This article aims to record and help those who need it.
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'As shown above, keyof extracts the keys of an interface. Understanding keyof is essential for the advanced types that follow: Record, Pick.
Prerequisite: Mapped Types
Mapped types allow you to quickly create types:
type NewUser = {
[K in 'name' | 'mobile']: string;
};
// The above code 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;
};With prerequisites covered, let's move on to TypeScript's advanced types.
Record Type
The Record type is the most commonly 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;
};The code is self-explanatory. Combined with the prerequisites:
type User = Record<'name' | 'mobile', string>;
// The above code 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 in daily development, hence this record.
