TypeScript Utility Types
TypeScript ships with a set of built-in helper types that change or reuse other types. These are called utility types.
This chapter covers the most popular ones.
Partial
Partial takes an object type and makes every property optional.
Example
Partial<Point> lets you start with an empty object and fill in x and y later.
Partial utility type makes every property of an object type optional.
Declare a Point interface with x: number and y: number, create pointPart typed as Partial<Point> starting from an empty object literal, then assign pointPart.x = 10. The file only declares and assigns; it prints nothing.
Output: TypeScript file and captured output
interface Point {
x: number;
y: number;
}
let pointPart: Partial<Point> = {}; // `Partial` allows x and y to be optional
pointPart.x = 10;
Required
Required takes an object type and makes every property required, even the ones marked optional with ?.
Example
mileage is optional in Car, but Required<Car> forces you to give it a value.
Required utility type turns optional properties into required ones.
Declare a Car interface with make: string, model: string and an optional mileage?: number, then create myCar typed as Required<Car> with make 'Ford', model 'Focus' and mileage 12000, adding a comment that Required forces mileage to be defined. Nothing is printed.
Output: TypeScript file and captured output
interface Car {
make: string;
model: string;
mileage?: number;
}
let myCar: Required<Car> = {
make: 'Ford',
model: 'Focus',
mileage: 12000 // `Required` forces mileage to be defined
};
Record
Record is a short way to describe an object type with one key type and one value type.
Note: Record<string, number> means the same as { [key: string]: number }.
Example
Every key in nameAgeMap must be a string and every value must be a number.
Record utility type used to describe a map from string keys to number values.
Create a constant nameAgeMap typed as Record<string, number> holding 'Alice' with 21 and 'Bob' with 25. Nothing is printed.
Output: TypeScript file and captured output
const nameAgeMap: Record<string, number> = {
'Alice': 21,
'Bob': 25
};
Omit
Omit removes the keys you name from an object type.
Example
Omit<Person, 'age' | 'location'> leaves only name, so age and location cannot be set on bob.
Omit utility type removes named keys from an object type.
Declare a Person interface with name: string, age: number and optional location?: string, then create bob typed as Omit<Person, 'age' | 'location'> holding only name 'Bob', with a comment explaining that age and location were removed and cannot be defined here. Nothing is printed.
Output: TypeScript file and captured output
interface Person {
name: string;
age: number;
location?: string;
}
const bob: Omit<Person, 'age' | 'location'> = {
name: 'Bob'
// `Omit` has removed age and location from the type and they can't be defined here
};
Pick
Pick keeps only the keys you name and removes everything else from an object type.
Example
Pick<Person, 'name'> keeps only name, so age and location are gone from the type.
Pick utility type keeps only the named keys of an object type.
Declare a Person interface with name: string, age: number and optional location?: string, then create bob typed as Pick<Person, 'name'> holding only name 'Bob', with a comment explaining that only name was kept so age and location cannot be defined here. Nothing is printed.
Output: TypeScript file and captured output
interface Person {
name: string;
age: number;
location?: string;
}
const bob: Pick<Person, 'name'> = {
name: 'Bob'
// `Pick` has only kept name, so age and location were removed from the type and they can't be defined here
};
Exclude
Exclude removes members from a union type.
Example
After Exclude<Primitive, string> the value can be a number or a boolean, but not a string.
Exclude utility type removes a member from a union type.
Declare a Primitive type alias as string | number | boolean, then create a constant value typed as Exclude<Primitive, string> set to true, with a comment noting that a string cannot be used here because Exclude removed it. Nothing is printed.
Output: TypeScript file and captured output
type Primitive = string | number | boolean
const value: Exclude<Primitive, string> = true; // a string cannot be used here since Exclude removed it from the type.
ReturnType
ReturnType takes a function type and gives you the type of what that function returns.
Example
ReturnType<PointGenerator> is the object type { x: number; y: number; }.
ReturnType utility type extracts the return type of a function type.
Declare a PointGenerator type alias for a function with no parameters returning { x: number; y: number; }, then create a constant point typed as ReturnType<PointGenerator> with x 10 and y 20. Nothing is printed.
Output: TypeScript file and captured output
type PointGenerator = () => { x: number; y: number; };
const point: ReturnType<PointGenerator> = {
x: 10,
y: 20
};
Parameters
Parameters takes a function type and gives you its parameter types as a tuple (an array type). You can index it to get one parameter's type.
Example
Parameters<PointPrinter>[0] is the type of the first parameter: { x: number; y: number; }.
Parameters utility type extracts a function type's parameter types as a tuple.
Declare a PointPrinter type alias for a function taking p: { x: number; y: number; } and returning void, then create a constant point typed as Parameters<PointPrinter>[0] with x 10 and y 20. Nothing is printed.
Output: TypeScript file and captured output
type PointPrinter = (p: { x: number; y: number; }) => void;
const point: Parameters<PointPrinter>[0] = {
x: 10,
y: 20
};
Readonly
Readonly makes a new type where every property is read-only. Once a property has a value, it cannot be changed.
Note: TypeScript stops the change at compile time only. The compiled JavaScript has no such protection, so a readonly property can still be overwritten at runtime.
Example
Assigning a new name to a Readonly<Person> is a compile error.
Readonly utility type blocks assignment to properties after creation.
Declare a Person interface with name: string and age: number, create a constant person typed as Readonly<Person> with name "Dylan" and age 35, then try to assign 'Israel' to person.name. Keep that line so the compiler reports error TS2540 (cannot assign to a read-only property).
Output: TypeScript file and captured output
interface Person {
name: string;
age: number;
}
const person: Readonly<Person> = {
name: "Dylan",
age: 35,
};
person.name = 'Israel'; // prog.ts(11,8): error TS2540: Cannot assign to 'name' because it is a read-only property.