Typescript union object types to interface type

I want to convert TypeScript union object types into interface type:

type ActionTypes = { action: 'A', data: number }
| { action: 'B', data: string }
| { action: 'C' }

// to: { A: number, B: string, C: undefined or never ? }

Typescript Playground

>Solution :

You could use key remapping via as to iterate over the union members of ActionTypes and pull out the action prop as a key and the data prop as a value (if it exists). Like this:

type Actions<T extends { action: string, data?: any }> = {
  [U in T as U["action"]]: "data" extends keyof U ? U["data"] : UndefinedOrNever
}

(I don’t know whether you want undefined or never so just define UndefinedOrNever to be what you want). Let’s test it out:

type ActionTypes = { action: 'A', data: number }
  | { action: 'B', data: string }
  | { action: 'C' }

type ActionsType = Actions<ActionTypes>

/* type ActionsType = {
    A: number;
    B: string;
    C: UndefinedOrNever;
} */

Looks good!

Playground link to code

Leave a Reply