Search code examples
typescripttypescript-types

Create an union type from interface properties


Consider the following interface

type State = {
  data: any[]
  index: number
  size: number
  count: number
  loading: boolean
  error: string | undefined
}

I need to create a type that is the union of its properties that should be like

{data: any[]} | {index: number} | {size: number} |...

So far I'm able to merge all the return types by using an indexed type access but I will get the union of the return types of the interface properties.


Solution

  • You need to use distributive-conditional-types:

    type State = {
        data: any[]
        index: number
        size: number
        count: number
        loading: boolean
        error: string | undefined
    }
    
    type Split<T> = keyof T extends infer Keys // turn on distributivity
        ? (Keys extends PropertyKey
            ? (Keys extends keyof T
                ? Record<Keys, T[Keys]> // apply to each key, or { [prop in Keys]: T[Keys] }for readability
                : never)
            : never)
        : never
    
    //  Record<"data", any[]> | Record<"index", number> | Record<"size", number> ...
    type Result = Split<State>
    

    Playground