Skip to content

Todo Data Model

Medium~30 min

What you'll build

A `todos` array of task objects `{ id, title, done }` plus three pure functions: `addTodo`, `toggleTodo`, and `listTodos` that operate on the array.

Goals

  • Model a real-world entity (a task) as an object
  • Use an array as a collection and mutate it safely
  • Write functions that take state and return new state
  • Practice unique-id generation with a counter

Prerequisites

  • Objects and property access
  • Arrays and array methods (push, map, find)
  • Functions with parameters

Steps

  1. 1

    Define a task shape

    Decide what a single task looks like. A minimal task has an id (number), a title (string), and a done (boolean). Write a helper makeTask(id, title) that returns such an object so every task is shaped consistently.

    Code
    function makeTask(id, title) {
      return { id, title, done: false };
    }

    Expected result

    makeTask(1, "Learn loops") returns { id: 1, title: "Learn loops", done: false }.

  2. 2

    Set up the collection

    Create a todos array and a nextId counter starting at 1. The counter guarantees every task gets a unique id even after deletions.

    Code
    let todos = [];
    let nextId = 1;

    Expected result

    An empty list and a counter ready to assign id 1 to the first task.

  3. 3

    Implement addTodo

    Write addTodo(title) that creates a task with the current nextId, pushes it to todos, increments nextId, and returns the new task. Returning the task lets the caller know what was added.

    Code
    function addTodo(title) {
      const task = makeTask(nextId, title);
      todos.push(task);
      nextId++;
      return task;
    }

    Expected result

    addTodo("Buy milk") returns the task and todos now has length 1.

  4. 4

    Implement toggleTodo

    Write toggleTodo(id) that finds the task by id and flips its done flag. If the id is not found, return a message. Finding by id is safer than by title because titles can repeat.

    Code
    function toggleTodo(id) {
      const task = todos.find(t => t.id === id);
      if (!task) return "Task not found";
      task.done = !task.done;
      return task;
    }

    Expected result

    After toggling id 1, that task's done flag flips from false to true.

  5. 5

    Implement listTodos and test

    Write listTodos() that returns a readable list of all tasks. Then add three tasks, toggle one, and print the list to confirm the model works end-to-end.

    Code
    function listTodos() {
      return todos.map(t =>
        `[${t.done ? "x" : " "}] #${t.id} ${t.title}`
      );
    }
    
    addTodo("Learn loops");
    addTodo("Write calculator");
    addTodo("Build todo model");
    toggleTodo(2);
    console.log(listTodos());

    Expected result

    Three lines printed: task #2 shows [x], the others show [ ].

Try it yourself

What you learned

You modeled a real feature as data (objects in an array) plus operations (functions), and used a counter for unique ids — the same shape used by production todo apps, just with a UI on top.

Related Resources

Related Lessons

  • Objects

    Objects represent each task in the model.

  • Arrays

    Arrays and methods like push, find, and map drive the collection.

  • Functions

    Functions encapsulate the operations on the model.

Related Practice

Related Tools

  • JSON Formatter

    Inspect the todos array as formatted JSON — exactly how it would be stored.

Related Cheatsheets

Related Reference

Related Errors

Related Glossary

  • Array

    Ordered collections of values.

  • Object

    Key-value data structures.

  • Data Type

    Kinds of values in code.

Related Glossary

A beginner-friendly glossary explains jargon in plain English — variables, functions, DOM, Promise, and more.

  • Array

    Ordered collections of values.

  • Object

    Key-value data structures.

  • Data Type

    Kinds of values in code.

Related Errors

Plain-English explanations of common errors — what they mean, why they happen, and how to fix them.

← Back to topic