TypeScript keyof index type is too wide

If you expect the keys of T to be a union of literals like "bong" | "bing" | ... (and not just string), then you can express a type which is itself the union of Column<T, K> for each key K in keyof T.

I usually do this via immediately indexing (lookup) into a mapped type:

type SomeColumn<T extends RowData> = {
  [K in keyof T]-?: Column<T, K>
}[keyof T]

but you can also do it via distributive conditional types:

type SomeColumn<T extends RowData> = keyof T extends infer K ?
  K extends keyof T ? Column<T, K> : never : never;

Either way, your RowsAndColumns type would then use SomeColumn instead of Column:

type RowsAndColumns<T extends RowData> = {
  rows: Array<T>;
  columns: Array<SomeColumn<T>>;
}

And this makes your desired use case work as expected without compile errors:

myFn({
  rows: [
    {
      id: "foo",
      bar: "bar",
      bing: "bing",
      bong: {
        a: 99,
        b: "aaa"
      }
    }
  ],
  columns: [
    {
      key: "bar",
      action: (value, rowData) => {
        console.log(value);
      }
    },
    {
      key: "bong",
      action: (value, rowData) => {
        console.log(value.a);
      }
    },
  ]
});

Playground link to code

Leave a Comment