Poznajemy inny, nieco bardziej zawiły sposób na reducer function w TypeScript. Ten akurat średnio mi się podoba, najlepszy poznamy w następnej lekcji, ale ok. Do dzieła!
Dodam, że ten sposób jest tym, na który sam wpadłem i w ten sposób reducerów używałem. Ale poznałem dużo lepszy, ale o tym później.
Dobra, taki enum:
enum CountActionKind {
INCREASE = 'INCREASE',
DECREASE = 'DECREASE',
CLEAR = 'CLEAR'
}
Nie wiem, czy pamiętamy/znamy interfejsy z literalnymi wartościami, ale właśnie na tym polega cały myk tego podejścia:
interface CountActionInc {
type: 'INCREASE';
payload: number;
}
interface CountActionDec {
type: 'DECREASE';
payload: number;
}
interface CounterActionClear {
type: 'CLEAR';
payload: undefined;
}
Był enum, były interfejsy, teraz typ:
type CountAction = CountActionInc | CountActionDec | CounterActionClear;
interface CountState {
count: number;
}
Teraz funkcja reducer:
function counterReducer(state: CountState, action: CountAction) {
const { type, payload } = action;
switch (type) {
case CountActionKind.INCREASE:
return {
...state,
count: state.count + payload,
};
case CountActionKind.DECREASE:
return {
...state,
count: state.count - payload,
};
case CountActionKind.CLEAR:
return {
...state, count: 0
};
default:
return state;
}
}
console.log(counterReducer({count: 0}, {type: CountActionKind.INCREASE, payload:1}))
//{ count: 1 }
Jak już zrozumiemy o co chodzi, to wklejmy sobie do edytora i zobaczmy, ile się trzeba narobić: enum, intefejsy, typ, interfejs stanu (typ też by obleciał). Jasne, w bardziej zaawansowanych przypadkach pewnie tak się będziemy bawili (takie przypadki, gdzie każda akcja będzie mieć zupełnie inny typ payloadu i będą to bardzo złożone typy).
Tym niemniej, w następnej lekcji poznamy coś łatwiejszego, coś takiego moim zdaniem w sam raz, dającego nam pewną swobodę w typach payloadu, ale bez przesady.