Typescript: Returnere en union basert på ReturnTypes i et objekt


Min opprinnelige kode er som følger, den lar meg oppdage typen data basert på type når jeg gjør en switch på 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;
  }
};

Det jeg gjerne vil vite er om jeg kan lage ActionType-unionen dynamisk ved å mappe over nøklene til AppActions?

Nærmeste svar så langt

@Elias sitt svar så langt av type ActionType=ReturnType<typeof AppActions[keyof typeof AppActions]>; kutter ut det meste av oppblåsingen her.

Ovenstående fungerer perfekt så lenge hver funksjon i AppActions har en angitt returtype. Uten dette kan typen av data ikke oppdages, men den oppdager korrekt at Actions.GET_MESSAGES_ERROR er en ugyldig action.type.

Svar #1

Dette svaret fungerer for å hente ut typen, men typevakter klarer ikke å løse og avsløre den underliggende typen!

Svar

type ActionType = ReturnType<typeof AppActions[keyof typeof AppActions]>;

Du trenger ikke engang å spesifisere returtypen til funksjonene:

const AppActions = {
    getMessages() {
        return {
            messages: ["asdf"],
        };
    },
    getMessagesLoaded() {
        return {
            loadedMessages: [1],
        }
    },
};