Search code examples
typescriptgenericsunionkeyof

How to create a type derived from an union type in typescript


I have the following type

type DataTableCol<T, K extends keyof T> = {
  title: string;
  key: K;
  render?: (value: T[K]) => ReactElement;
};

I need to create another type, DataTableRow<T>, derived from it. From type MyData = { name: string; value: number; }, it will have the following form:

type DataTableRow<MyData> = (DataTableCol<MyData, 'name'> | DataTableCol<MyData, 'value'>)[]

It will basically be an array of a new union type, mapped for each keyof T, I want to use generics because this code will be reusable. Is this possible?


Solution

  • You can use a distributive conditional type:

    type DataTableCol<T, K extends keyof T> = {
      title: string;
      key: K;
      render?: (value: T[K]) => any;
    };
    
    type Distribute<T, K> = K extends keyof T ? DataTableCol<T, K> : never;
    
    type DataTableRow<T> = (Distribute<T, keyof T>)[];
    
    type MyData = { name: string; value: number; };
    
    type Foo = DataTableRow<MyData>;
    // (DataTableCol<MyData, "name"> | DataTableCol<MyData, "value">)[]
    

    Playground