简体   繁体   中英

Typescript union type to single mapped type

Is it possible to convert a union type to a map with the key being "type" property? eg Given a union type Actions:

type Actions =
  | {
      type: 'campaignCreated';
      code: string;
    }
  | {
      type: 'campaignEnded';
      amount: number;
    };

I'd like to be able to receive;

type ActionMap = {
  campaignCreated: {
    type: 'campaignCreated';
    code: string;
  };
  campaignEnded: {
    type: 'campaignEnded';
    amount: number;
  };
};

Yes it's possible.

We start with a type for selecting a single union member based on the type type:

type ActionSelector<T extends Actions['type'], U extends {type: Actions['type']}> = 
    U extends {type: T} ? U : never;

It works because conditional types distribute the condition over the members of the union type, when the condition argument is a union.

Just a check that it works as expected:

type A1 = ActionSelector<'campaignCreated', Actions>

Then we can use it as 'value type' in a mapped type:

type ActionMap = {[t in Actions['type']]: ActionSelector<t, Actions>};

the result is

type ActionMap = {
    campaignCreated: {
        type: "campaignCreated";
        code: string;
    };
    campaignEnded: {
        type: "campaignEnded";
        amount: number;
    };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM