Let's say I have a union type as follows:
type State = {
value: number
things: []
}
type Action =
| {
type: 'INCREMENT'
data: number
}
| {
type: 'DECREMENT'
data: number
}
| {
type: 'DO_THING'
data: {
id: string
name: string
}
}
And a reducer function like so:
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'INCREMENT':
return increment(state, action)
case 'DECREMENT':
return decrement(state, action)
case 'DO_THING':
return addItem(state, action)
default:
return state
}
}
When typing my little action helper functions, I'm greeted with an error. Example:
function increment(state: State, action: action): State {
return {
...state,
number: action.data 1 // this is the culprit
}
}
Basically, because of the union type for which data
is either number
or the object defined, I'm getting an error like so:
Type 'number | { id: string; value: string }' is not assignable to type 'number'
I get why the error is here, because value
is indeed strongly typed as just number
. But… how do I solve this? How do I correctly type things to make it all play nice?
CodePudding user response:
You can use the Extract utility to pull out the Increment action by its type.
function increment(state: State, action: Extract<Action, { type: 'INCREMENT' }>): State {
return {
...state,
value: action.data 1,
};
}