Skip to content
dreamcode
dreamcode
Projects
Typed Store
Capstone projectTypeScript
Reward: +600 XP
PROJECT BRIEF

Typed Store

Most front-end apps keep their data in a store that changes only through actions. Write applyActions(initial, actions) that replays a list of actions over a to-do state and returns the final state.

  • add: append a to-do { id, text, done: false }, where id is one more than the highest id so far (1 for an empty list)
  • toggle: flip done on the to-do with that id
  • rename: change the text of the to-do with that id
  • remove: delete the to-do with that id
  • clearDone: delete every finished to-do

Actions that name an id that does not exist change nothing. Never mutate initial or the to-dos inside it: build new arrays and objects, the same rule React and Redux rely on.

Build it step by step
  1. Write reducer as a switch on action.type.
  2. For add, compute the next id with Math.max(0, ...state.todos.map((t) => t.id)) + 1.
  3. For toggle and rename, map over the to-dos and spread the one that matches: { ...t, done: !t.done }.
  4. For remove and clearDone, use filter.
  5. applyActions is already done: reduce replays every action through your reducer.
Examples
applyActions({ todos: [] }, [{ type: "add", text: "pack" }, { type: "add", text: "fly" }, { type: "toggle", id: 1 }, { type: "rename", id: 2, text: "fly high" }])
{ todos: [{ id: 1, text: "pack", done: true }, { id: 2, text: "fly high", done: false }] }
applyActions({ todos: [{ id: 7, text: "old", done: false }] }, [{ type: "add", text: "new" }, { type: "remove", id: 7 }])
{ todos: [{ id: 8, text: "new", done: false }] }
project.ts
TYPESCRIPT
Saved as you type

Tests

0 of 5 passing
  • add, toggle, rename
    applyActions({ todos: [] }, [{ type: "add", text: "pack" }, { type: "add", text: "fly" }, { type: "toggle", id: 1 }, { type: "rename", id: 2, text: "fly high" }])
    expected { todos: [{ id: 1, text: "pack", done: true }, { id: 2, text: "fly high", done: false }] }
  • ids continue after the highest
    applyActions({ todos: [{ id: 7, text: "old", done: false }] }, [{ type: "add", text: "new" }, { type: "remove", id: 7 }])
    expected { todos: [{ id: 8, text: "new", done: false }] }
  • clearDone keeps open tasks
    applyActions({ todos: [{ id: 1, text: "a", done: true }, { id: 2, text: "b", done: false }, { id: 3, text: "c", done: true }] }, [{ type: "clearDone" }, { type: "add", text: "d" }])
    expected { todos: [{ id: 2, text: "b", done: false }, { id: 3, text: "d", done: false }] }
  • unknown ids change nothing
    applyActions({ todos: [{ id: 1, text: "a", done: false }] }, [{ type: "toggle", id: 9 }, { type: "rename", id: 9, text: "z" }, { type: "remove", id: 9 }])
    expected { todos: [{ id: 1, text: "a", done: false }] }
  • no actions
    applyActions({ todos: [] }, [])
    expected { todos: [] }
On the line
+600 XP
Pass all 5 tests to claim it.