

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: flipdoneon the to-do with that idrename: change the text of the to-do with that idremove: delete the to-do with that idclearDone: 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
- Write
reduceras aswitchonaction.type. - For
add, compute the next id withMath.max(0, ...state.todos.map((t) => t.id)) + 1. - For
toggleandrename,mapover the to-dos and spread the one that matches:{ ...t, done: !t.done }. - For
removeandclearDone, usefilter. applyActionsis already done:reducereplays 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, renameapplyActions({ 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 highestapplyActions({ 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 tasksapplyActions({ 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 nothingapplyActions({ 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 actionsapplyActions({ todos: [] }, [])expected { todos: [] }
On the line
+600 XP
Pass all 5 tests to claim it.
