Let's think about this for a second
In this part, we'll reorganize the code from Part 1 — which used global variables and standalone functions — into a class. Using classes lets us bundle state (the tasks array) and behavior (addTask, listTasks) together in one place, and encapsulate data with private fields. We'll also add a method that uses union types and type narrowing to filter tasks by status. This step will make it clear just how useful a class-based structure is in real-world applications.
Let's build it
Create a TaskManager class with the fields private tasks: Task[] = [] and private nextId: number = 1. Rewrite the addTask() and listTasks() methods from Part 1 inside the class. Add a new method, updateStatus(id: number, status: TaskStatus): boolean, that finds the task with the matching id in the tasks array and updates its status (returning false if it's not found). Also add filterByStatus(status: TaskStatus): Task[], which returns a new array containing only the tasks matching the given status (use Array.filter()). Finally, create a TaskManager instance, add some tasks, update a status, filter, and test the result with console.log.
Sample code
class TaskManager {
private tasks: Task[] = [];
private nextId: number = 1;
addTask(title: string, priority: Task["priority"]): Task {
const task: Task = {
id: this.nextId++,
title,
status: TaskStatus.Todo,
priority,
};
this.tasks.push(task);
return task;
}
listTasks(): void {
this.tasks.forEach((t) =>
console.log(`#${t.id} [${t.status}] ${t.title} (${t.priority})`)
);
}
updateStatus(id: number, status: TaskStatus): boolean {
const task = this.tasks.find((t) => t.id === id);
if (!task) return false;
task.status = status;
return true;
}
filterByStatus(status: TaskStatus): Task[] {
return this.tasks.filter((t) => t.status === status);
}
}
const manager = new TaskManager();
manager.addTask("Learn generics", "high");
manager.addTask("Deploy project", "medium");
manager.updateStatus(1, TaskStatus.InProgress);
console.log("In Progress tasks:");
manager.filterByStatus(TaskStatus.InProgress).forEach((t) =>
console.log(`- ${t.title}`)
);Under the "In Progress tasks:" heading, only the title of the task whose status was updated ("Learn generics") is shown.5-minute try it yourself
Add a method removeTask(id: number): boolean to the TaskManager class, and implement it so it removes the task with the matching id from the tasks array using filter().
A quick word of caution
Keep in mind that Array.find() returns a reference to the object it finds, so changing a field on it can directly mutate the object inside the original array too — watch out for this side effect.