Код Senior Объединения и сужение обновлено
Конечный автомат платежа с типами переходов
Условие
Платёж проходит состояния: pending → authorized → captured → refunded; из pending и authorized можно уйти в cancelled; из pending в failed.
Опиши:
PaymentStateкак union по полюstatus, где уauthorizedестьauthCode: string, уcapturedиrefundedестьcapturedAmount: number, уfailedестьreason: string;PaymentEvent:authorize { authCode },capture { amount },refund,cancel,fail { reason };transition(state, event): возвращает{ ok: true; state }или{ ok: false; error }с текстомcannot <event> in <status>. Захват суммы<= 0даётinvalid amount.
replay(events) применяет события к { status: 'pending' }, останавливаясь на первой ошибке, и возвращает итоговое состояние или ошибку.
Примеры
replay([{"type":"authorize","authCode":"A1"}, {"type":"capture","amount":500}]) // {"ok":true,"state":{"status":"captured","authCode":"A1","capturedAmount":500}}
replay([{"type":"authorize","authCode":"A1"}, {"type":"capture","amount":500}, {"type":"refund"}]) // {"ok":true,"state":{"status":"refunded","capturedAmount":500}}
replay([{"type":"capture","amount":100}]) // {"ok":false,"error":"cannot capture in pending"}
Как подойти
Подсказки: 2
- Сначала
switchпо событию, внутри проверка статуса: послеstate.status !== "authorized"TS знает, что у состояния естьauthCode. - Если
switchпо всем вариантам события возвращает значение, TS не потребуетreturnпосле него.
Решите в тренажёре
Редактор с автотестами прямо в браузере. Можно решить спокойно, вслух или под таймером, как на собесе.
Предыдущий вопрос
Безопасный парсинг JSON в тип через type guard
Следующий вопрос
Площадь фигур: union с разными полями