SKIP TO MAIN
-- views

Deep Dive Into Typescript's Utility Types

February 18, 2024

TypeScript comes with a large number of predefined generic types that can help with some common type manipulation

Utility Types#

Utility types help to manipulate or create other new types from existing ones

Partial<Type>#

The Partial type takes in another Type and produces a type where all of its properties are optional.

Consider we have the following interface:

type Todo = {
	title: string;
	description: string;
};

If we want to create a type where all of its properties are optional:

type PartialTodo = Partial<Todo>;

This is equivalent to:

type PartialTodo = {
	title?: string;
	description?: string;
};

Required<Type>#

The opposite of Partial; The Required type takes in another Type and produces a type where all of its properties are required.

Consider we have the following interface:

type Todo = {
	title?: string;
	description?: string;
};

If we want to create a type where all of its properties are required:

type RequiredTodo = Required<Todo>;

This is equivalent to:

type RequiredTodo = {
	title: string;
	description: string;
};

Readonly<Type>#

Create a new type where all properties of Type are set to read-only, meaning the properties are immutable

interface Todo {
	title: string;
}
 
const todo: Readonly<Todo> = {
	title: "Delete inactive users",
}
 
todo.title = "Hello";
// Cannot assign to 'title' because it is a read-only property.

Record<Keys, Type>#

This utility creates an object type with properties of specified Keys and values of another specified Type

interface CatInfo {
	age: number;
	breed: string;
}
 
type CatName = "miffy" | "boris" | "mordred";
 
const cats: Record<CatName, CatInfo> = {
	miffy: { age: 10, breed: "Persian" },
	boris: { age: 5, breed: "Maine Coon" },
	mordred: { age: 16, breed: "British Shorthair" },
}

Pick<Type, Keys>#

Creates a new type by extracting a specified Keys from Type

interface Todo {
	title: string;
	description: string;
	completed: boolean;
}
 
type TodoPreview = Pick<Todo, "title" | "completed">;

This is equivalent to:

type TodoPreview = {
	title: string;
	completed: boolean;
};

Omit<Type, Keys>#

The opposite of Pick; creates a new type by excluding specified Keys from the original Type

interface Todo {
	title: string;
	description: string;
	completed: boolean;
}
 
type TodoPreview = Omit<Todo, "completed">;

This is equivalent to:

type TodoPreview = {
	title: string;
	description: boolean;
};

Exclude<UnionType, ExcludedMembers>#

Creates a new type by excluding specified ExcludedMembers from a given UnionType.

type Size = 'xl' | 'lg' | 'md' | 'sm' | 'xsm';
 
type ExcludedSize  = Exclude<Size, 'xl' | 'lg'>;

This is equivalent to:

type ExcludedSize = 'md' | 'sm' | 'xsm';

NonNullable<Type>#

Creates a new type by omitting null and undefined from Type

type NonNullableType = NonNullable<string | number | undefined | null>;

This is equivalent to:

type NonNullableType = string | number;

Parameters<Type>#

Creates a new type by extracting the parameters Type of a function

type MathOperation = (a: number, b: number) => number;
 
type OperationParameters = Parameters<MathOperation>;

This is equivalent to:

type OperationParameters = [a: number, b: number];

Conclusion#

  • Utility Types reduce redundancy and ensure the type stays up to date with the original type.

References#

GET IN TOUCH

Let’s work together

I build exceptional and accessible digital experiences for the web

WRITE AN EMAIL