Reputation: 691
I have a reducer named Messages, that will have the following actions.
GET_MESSAGE_START & RESET_MESSAGE -> Payload will have {chatUser: "username"}
GET_MESSAGE_SUCCESS -> Payload will have {chatUser: "username",nextPage: 2,count: 22,messages:Array<InboxMessages>}
GET_MESSAGE_FAIL -> Payload will have {error:[Error]}
GET_SOCKET_MESSAGE -> Payload will have {chatUser: "username", message: <InboxMessages> }
Interface
// For Reusing
export interface errorInterface{
error?:null|string|Array<string>|{[key:string]:any}
}
// For Reusing
export interface BaseLoadingInterface {
loading: boolean
}
// For Reusing
export interface NextPageInterface {
nextPage: number | null
}
export interface InboxMessages {
id: number,
user: userInterface,
receiver: userInterface,
message: string,
timestamp: Date,
thread: number,
attachment: any
}
export interface MessageInboxInterface extends BaseLoadingInterface, NextPageInterface{
user: string,
messages: Array<InboxMessages>,
count: number,
}
export interface MessageStateInterface extends errorInterface{
chatUser: string | null,
inbox: Array<MessageInboxInterface>
}
export interface MessagePayload {
chatUser: string,
nextPage: null | number,
count: number,
messages: Array<InboxMessages>
}
export interface MessageStartInterface {
type: typeof GET_MESSAGES_START | typeof RESET_MESSAGE,
payload:{
chatUser: string
}
}
export interface MessageSuccessInterface{
type: typeof GET_MESSAGES_SUCCESS,
payload:MessagePayload
}
export interface MessageFailInterface {
type: typeof GET_MESSAGES_FAIL,
payload: errorInterface
}
export interface SocketMessageInterface{
type: typeof GET_SOCKET_MESSAGE,
payload: InboxMessages
}
export type MessageAction = MessageStartInterface | MessageSuccessInterface | SocketMessageInterface
Reducer
const defaultMessagesState:MessageStateInterface = {
chatUser:null,
error:null,
inbox:[],
};
export const userChatMessageReducer = (state:MessageStateInterface=defaultMessagesState, action:MessageActionInterface) => {
const{type,payload}=action;
const chatUserInbox = state.inbox.filter(el => el.user === payload.chatUser);
const inbox = state.inbox.filter(el => el.user !== payload.chatUser);
switch (type) {
case GET_MESSAGES_START:
// Returns a updated User Inbox
getMessageStartInbox(state, payload)
return{
...state,
chatUser:payload.chatUser,
inbox: inbox
};
case GET_MESSAGES_SUCCESS:
// Returns a updated Inbox with messages
return {
...state,
inbox: [...inbox,getInboxMessage(state, payload)]
};
case GET_SOCKET_MESSAGE:
// Initiate New Message From Socket and returns new message
return {
...state,
inbox: [...inbox,newInboxObject(state, payload.message)]
};
case RESET_MESSAGE:
// Delete chat user's message
return {
...state,
inbox:[...inbox]
};
case GET_MESSAGES_FAIL:
return {
...state,
error: payload.error
};
default:
return state
}
};
But I am getting errors, saying, chatUser, messages, message not in MessageActionInterface -> Payload type. Those are not a valid type for MessageActionInterface.payload
Upvotes: 0
Views: 1827
Reputation: 42160
The reason that you are getting errors within the branches of your switch statement is due to a small technicality. When you destructure the action
object outside of the switch
statement, Typescript assigns a type to both type
and payload
. They now have their own types, so Typescript isn't considering the relationship between them. Each case
of the switch
refines the type definition for type
but not for payload
.
The solution is simple: don't desctructure the action
object. Use switch (action.type)
and replace refences to payload
with action.payload
.
There is one more potential issue which is accessing payload.chatUser
outside of the switch
to generate the inbox
. It seems like not all action types have a chatUser
property (should user
in InboxMessages
be chatUser
?).
We can conditionally access chatUser
using a guard 'chatUser' in action.payload
to make sure that the property exists. If not, we return null
and get an empty array for the inbox
.
const chatUser = ( 'chatUser' in action.payload ) ? action.payload.chatUser : null;
const inbox = state.inbox.filter(el => el.user !== chatUser);
Upvotes: 1