TypeScriptLesson 16 of 16
Mini project: a typed task tracker
The last lesson brings it all together: an interface, a union of literals, utility types and a class with private state. The skeleton is ready, and three methods are left to write.
Key points
- Priority is a union of literals, not an enum.
- readonly id cannot change after a task is created.
- NewTask = Omit<Task, "id" | "done">: the tracker fills those fields itself.
- Record<Priority, number> sets the sort order and will not let you forget a priority.
- private tasks: from outside, the list changes only through the methods.
Example
type NoteStatus = "todo" | "done"; interface Note { readonly id: number; text: string; status: NoteStatus;} class NoteBook { private notes: Note[] = []; add(text: string): Note { const note: Note = { id: this.notes.length + 1, text, status: "todo" }; this.notes.push(note); return note; } finish(id: number): void { const note = this.notes.find((item) => item.id === id); if (note) note.status = "done"; } count(status: NoteStatus): number { return this.notes.filter((note) => note.status === status).length; }} const book = new NoteBook();book.add("Buy milk");book.add("Call Sam");book.finish(1);console.log(`todo: ${book.count("todo")}, done: ${book.count("done")}`);The example is a smaller version of the project: notes with a status, a private array and a counting method. The task adds sorting by priority and statistics.
Task
How to use the editor⌘ Enter or Ctrl Enter runs the code, ⇧ ⌘ Enter checks the task.Tab and Shift Tab indent the line or the selection; Esc, then Tab leaves the editor.The check compares what the program printed with the task; spaces at line ends do not matter.After two failed checks you may open the solution. Your code is kept in this browser.Finish complete, pending and stats. Output: "Complete #2: true", "Complete #9: false", then the open tasks by priority — "[high] Review PR", "[medium] Write README", "[low] Update icons" — and "Done: 1, open: 3".
Output
What your program prints appears here.