Intermediate Exercism • typescript

Utility Types

Lesson Overview

Master TypeScript's built-in utility types like Partial, Readonly, Pick, and Omit.

Utility Types

TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally.

Partial<Type>

Constructs a type with all properties of Type set to optional. This is useful for “update” functions.

interface Todo {
  title: string;
  description: string;
}

function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  return { ...todo, ...fieldsToUpdate };
}

const todo1 = { title: "organize desk", description: "clear clutter" };
const todo2 = updateTodo(todo1, { description: "throw out trash" });

Readonly<Type>

Constructs a type with all properties of Type set to readonly, meaning the properties of the constructed type cannot be reassigned.

interface Todo {
  title: string;
}

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

Pick<Type, Keys>

Constructs a type by picking a set of properties Keys (string literal or union of string literals) from Type.

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Pick<Todo, "title" | "completed">;

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};

Omit<Type, Keys>

Constructs a type by picking all properties from Type and then removing Keys (string literal or union of string literals).

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoInfo = Omit<Todo, "completed">;

const todo: TodoInfo = {
  title: "Clean room",
  description: "Sweep and mop the floor",
};

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.

interface PageInfo {
  title: string;
}

type Page = "home" | "about" | "contact";

const nav: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};

These utilities are essential for keeping your type definitions DRY (Don’t Repeat Yourself) and making your code more expressive.