Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: Returning a union based on ReturnTypes in object

Tags:

typescript

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.

like image 302
Kyle Johnson Avatar asked Nov 22 '25 20:11

Kyle Johnson


1 Answers

This answer works in extracting the type, but type guards fail to resolve and reveal the underlying type!

enter image description here

enter image description here

Anser

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],
        }
    },
};
like image 139
Elias Avatar answered Nov 28 '25 00:11

Elias



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!