Reputation: 961
My initial code is as follows, it allows me to detect the type of data based on the type when doing a switch on action:ActionType.
enum Actions {
GET_MESSAGES,
GET_MESSAGES_LOADED
}
//@ts-ignore
const AppActions = {
getMessages() {
return {
type: Actions.GET_MESSAGES,
data:{id: 1}
};
},
getMessagesLoaded() {
return {
type: Actions.GET_MESSAGES_LOADED,
data:{messages: ['asdf']}
};
}
};
type ActionType = ReturnType<typeof AppActions[keyof typeof AppActions]>;
const func = (action:ActionType) => {
// @ts-ignore
switch (action.type) {
case Actions.GET_MESSAGES:
console.log(action.data.id) //Should pass
break
case Actions.GET_MESSAGES_LOADED:
console.log(action.data.messages) //Should pass
break;
case Actions.GET_MESSAGES_ERROR: // Should throw typescript error
// default:
// break;
}
};
What I'd like to know is can I create the ActionType union dynamically by mapping over keys of AppActions?
Closest Answer so far
@Elias's answer so far of type ActionType = ReturnType<typeof AppActions[keyof typeof AppActions]>;
cuts out most of the bloat here.
The above works perfectly so long as each function in AppActions has a specified return type, without this the type of data cannot be detected however it does detect correctly Actions.GET_MESSAGES_ERROR is an invalid action.type.
Upvotes: 3
Views: 56
Reputation: 4141
This answer works in extracting the type, but type guards fail to resolve and reveal the underlying type!
type ActionType = ReturnType<typeof AppActions[keyof typeof AppActions]>;
You don't even need to specify the return type of the functions:
const AppActions = {
getMessages() {
return {
messages: ["asdf"],
};
},
getMessagesLoaded() {
return {
loadedMessages: [1],
}
},
};
Upvotes: 1