BACK
Lessons44. scan as a reducer
Lessons · 44

44. scan as a reducer

The reducer pattern

Instead of "raw" numbers, you can use actions — objects that describe what happened. This is the core idea of Redux/NgRx, and it maps beautifully onto scan.

actions$.pipe(scan(reducer, initialState))
// reducer(state, action) → newState

Glossary

  • Action — an object, usually with a type field, describing an event.
  • Reducer — a pure function (state, action) => newState.
  • State — the current "snapshot" of the app's data.

The NgRx analogy

NgRx is built on the same scheme: dispatched actions → reducer → new state → subscribers. This lesson is a compact, teaching-sized version of that larger pattern.

Your task

  1. Inside the reducer, check action.type:
  2. 'increment'return { count: state.count + 1 }
  3. 'decrement'return { count: state.count - 1 }
  4. Otherwise return state unchanged.
  5. Important: don't mutate state — return a new object.
  6. Expected output: Count: 1 → Count: 2 → Count: 1.
Solution spoiler · click to reveal
const { from, scan } = Rx;

const actions$ = from([
  { type: 'increment' },
  { type: 'increment' },
  { type: 'decrement' },
]);

const state$ = actions$.pipe(
  scan((state, action) => {
    if (action.type === 'increment') {
      return { count: state.count + 1 };
    }

    if (action.type === 'decrement') {
      return { count: state.count - 1 };
    }

    return state;
  }, { count: 0 })
);

state$.subscribe(state => console.log('Count: ' + state.count));
script.ts // TypeScript
CONSOLE · Console output
Hit Run to see the result...