I am trying to type action names
but something I’m doing wrong.
It throws an error when I try to use it on reducer
function when trying to call updateProduct
function, even though I typed action names correctly.
Property 'update' does not exist on type 'ActionDelete'.
Here is the way I tried to implement it.
I’ve created an enum
for action names
and used them according to action type and type Action
is an alias which is either ActionUpdate
or ActionDelete
.
enum ActionTypes {
update = 'update',
delete = 'delete'
}
interface ActionUpdate {
type: ActionTypes.update;
update: string;
}
interface ActionDelete {
type: ActionTypes.delete;
delete: string;
}
type Action =
| ActionUpdate
| ActionDelete
I’ve created an interface for a call signature with positional arguments
interface ActionProps {
(
product: Product,
value: Value,
cart: Cart,
action?: Action
): void;
}
And here is the rest of usage of Action in reducer function.
Reducer function
const Reducer = (
product: Product,
value:Value,
cart: Cart,
action: Action,
) => {
switch (action.type) {
case 'update':
updateProduct( product, value, cart);
break;
default: {
throw new Error('Unknown type');
}
}
};
And as an example here is updateProduct
functon for update
const updateProduct: ActionProps = ( product, value, cart, action) => {
cart.name = action.update; // Error throws here on "action.update"
};
Here is a link for testing
Any help will be appreciated
2
Answers
This is happening because your
ActionProps
interface has an optional parameteraction?: Action
whereAction
can be eitherActionDelete
orActionUpdate
– in your code, you’re assuming thatActionProps
will only ever return anActionUpdate
type and therefore you don’t handle the case where the action could be ofActionDelete
typeThe easiest option would be to set the
action
inside ofActionProps
toActionUpdate
i.e.action?: ActionUpdate
(assuming that you won’t return anActionDelete
action in this scenario)Alternatively, it would be best if you restructured your types to be more explicit as to what you’re expecting so you can avoid these types of errors
You can make your
ActionProps
interface generic, defaulting toAction
. This way, you can optionally provide a specific action if you need to.Then in your definition of
updateProduct
, pass the right action type:Playground
You could just use a type alias instead of an interface: