I'm very new to typescript and I'm trying to write a reducer function with three possible payload values : no value, a string, or a number. I'm using discriminated union type and from what I have read I think my code should work, but it is not.
type StateType = {
isModalOpen: boolean;
modalContent: string;
people: {
id: number;
name: string;
}[];
};
type NoPayloadAction = {
type: string;
};
type NamePayloadAction = {
type: string;
payload: {
name: string;
};
};
type IdPayloadActionType = {
type: string;
payload: {
id: number;
};
};
type ActionType = NoPayloadAction | NamePayloadAction | IdPayloadActionType;
const ACTIONS = {
ADD_ITEM: 'ADD_ITEM',
NO_ACTION: 'NO_ACTION',
CLOSE_MODAL: 'CLOSE_MODAL',
REMOVE_ITEM: 'REMOVE_ITEM',
};
// reducer function
const reducer = (state: StateType, action: ActionType) => {
switch (action.type) {
case ACTIONS.ADD_ITEM:
return {
people: [
...state.people,
{ id: new Date().getTime(), name: action.payload.name },
],
isModalOpen: true,
modalContent: 'item added',
};
case ACTIONS.NO_ACTION:
return { ...state, isModalOpen: true, modalContent: 'enter a value' };
case ACTIONS.CLOSE_MODAL:
return { ...state, isModalOpen: false, modalContent: '' };
case ACTIONS.REMOVE_ITEM:
const newPeople = state.people.filter(
(person) => person.id !== action.payload.id
);
return {
people: [...newPeople],
isModalOpen: true,
modalContent: 'item removed',
};
default:
return state;
}
};
Typescript is throwing two errors: The lines below throws this error: Property 'payload' does not exist on type 'ActionType'. Property 'payload' does not exist on type 'NoPayloadAction'
{ id: new Date().getTime(), name: action.payload.name },
(person) => person.id !== action.payload.id
The type NoPayloadAction does not have a payload, but the other two do and from what I understand they match their types as one has an id:number field and the other has a name:string field. I'm really puzzled by this.
CodePudding user response:
Right now, there is no guarantee that what is being passed in to your action
variable is not a NoPayloadAction
. If you are sure that your action
variable does have a payload you can always use the as
keyword tell typescript you know what the variable is. For example:
return { id: new Date().getTime(), name: (action as NamePayloadAction).payload.name },