Редактор, конструктор, сложная форма. Пользователь должен иметь возможность откатить изменение (Ctrl+Z) и вернуть его обратно (Ctrl+Y). Модель: три списка — past, present, future.
Какую проблему решаем
Если хранить историю в массивах и мутировать их из обработчиков кнопок — рано или поздно past и future рассинхронизируются. Особенно после нового edit поверх старого undo: классическая ошибка — забыть очистить future, и redo применит «призрак» из удалённой ветки истории.
Операторы и зачем они нужны
Subject — принимает команды: edit, undo, redo, snapshot.
scan — это и есть наш reducer. Он держит {past, present, future} и применяет команды как чистая функция.
map — выделяет present для шаблона.
withLatestFrom — нужен для snapshot: «возьми текущее present в момент команды save».
Подводные камни
После нового edit обязательно чистить future. Иначе redo вернёт состояние из удалённой ветки истории.
Reducer должен быть чистым (никаких мутаций массивов in-place). Иначе OnPush change detection пропустит обновление.
BehaviorSubject с ручными next тоже работает, но scan-reducer чище тестируется через marble-тесты.
Что в итоге получаем
История превращается в предсказуемую state machine без императивных флагов. Логика undo/redo описана одной чистой функцией.