Introduction
In this article I'll be going over TypeScript utility types, explain their importance and also include some useful examples and use cases.
Utility types are built-in types that allow you to transform
existing types into new modified types.
Say we have type A
and we'd like to construct a new type B
that may inherit
, modify
or exclude
properties from type A
.
We achieve this by using a utility type i.e type B = UtilityType<A, options>
where UtilityType
represents the type to be used and options
describe the type of operation to perform e.g inherit
, modify
or exclude
etc.
Utility types aren't supported by
primitives
except strings which offerIntrinsic String Manipulation Types
to manipulate strings.
Utility types are usually used with compound types such asInterfaces
andUnion Types
.
Before you get started
The TypeScript playground is an excellent place to experiment with Utility Types. It's highly recommended to practice what you learn in order to solidify your understanding of the topic.
Union Types
A union type is a type formed from two or more other types, representing values that may be any one of those types. We refer to each of these types as the union’s members.
Union types basically combine
two or more types.
Unions support the following utility types:
This example to demonstrate how to use utility types with unions.
Caveat: Union types are
case-sensitive
.
type ActivityType =
"Swimming"
| "Reading"
| "Coding"
| "Dancing"
| "Jogging";
1 -Extract
Constructs a type by extracting from Type all union members that are assignable to Union.
Syntax Extract<Type, Union>
Where Type
is the initial type and Union
represents the entries we'd like to extract.
Demo
type CognitiveActivity = Extract<ActivityType, "Reading" | "Coding">;
// transformed type: "Reading" | "Coding"
const activity: CognitiveActivity = "Reading";
console.log(activity);
2 - Exclude
Constructs a type by excluding from UnionType all union members that are assignable to ExcludedMembers.
Syntax Exclude<UnionType, ExcludedMembers>
Where UnionType
is the initial type and ExcludedMembers
represents the entries we'd like to exclude.
Demo
type PhysicalActivity = Exclude<ActivityType, "Reading" | "Coding">;
// transformed type: "Swimming" | "Dancing" | "Exercise";
const activity: PhysicalActivity = "Swimming";
console.log(activity);
Type Aliases and Interfaces
Type Aliases: A type alias is a name for any type.
Interfaces: An interface declaration is another way to name an object type.
This example to demonstrate how to use utility types with type aliases and interfaces.
Intersection types are types that combine properties from two or more types. They're usually used in conjunction with the following utility types.
The general syntax is
type A = {
[key: string]: string;
};
type B = A & {
bKey: string;
}; // includes all the properties in A and B
type ElectronicDevice = {
name: string;
USBPorts: USBPORT[];
screenDimensions: Dimension;
buttons: Buttons[];
wifiConnectivity: boolean;
manufacturer: string;
memory: number;
}
This type represents the properties of an electronic device. Electronic devices come in a variety of shapes and sizes but they share a lot of core features such as buttons, memory, ports etc.
You can test the types in this example on this TypeScript playground.
1 - Pick
Syntax Pick<Type, Keys>
Constructs a type by picking the set of properties Keys (string literal or union of string literals) from Type.
Demo
type Calculator = Pick<ElectronicDevice, "name" | "buttons"> & {
type: CalculatorType;
// own types
}
2 - Record
Syntax Record<Keys, Type>
Constructs an object type whose property keys are Keys and whose property values are Type. This utility can be used to map the properties of a type to another type.
Demo
type DeviceType = "Analogue" | "Digital";
type SmartPhone = Record<DeviceType, ElectronicDevice> & {
type: CalculatorType;
// own types
}
const blackberry: SmartPhone = {
Digital: {
}
}
3 - Omit
Syntax Omit<Type, Keys>
Constructs a type by picking all properties from Type and then removing Keys (string literal or union of string literals).
Demo
type StopWatch = Omit<ElectronicDevice, "wifiConnectivity" | "USBPorts">;
4 - ReturnType
Syntax ReturnType<Type>
Constructs a type consisting of the return type of function Type.
Demo
const getUserByActivity = async (type: string) => {
const response = await apiCall(url, params); // fake api call
return response.data;
}
type NewUser = ReturnType<typeof getUserByActivity>
const user: NewUser = getUserByActivity(activity.type);
References: