Union of keyof keys from a type in typescript

61 Views Asked by At

I have these types:

type MyTableRowData = {
  id : string;
  name : string;
  total : number;
}

type TableDef<RowData> = {
  data: RowData[];
  columns: {
    [key in keyof RowData]: ColumnDef<key>;
  };
  enabledColumns: Array<string>; // I want here to be like an Array<"id" | "name" | "total">
}

So I can create the table:

const data : MyTableRowData[] = [
  {id: "1", name: "name1", total: 0},
  {id: "2", name: "name2", total: 10},
  {id: "3", name: "name3", total: 99},
]

const table : TableDef<MyTableRowData> = {
  data: data,
  columns: {
    id: {
      //not important here, but it's a ColumnDef object
    },
    name: {
      //not important to the question...
    },
    total: {
      //not important to the question...
    },
  },
  enabledColumns: ["name", "total"] // Here I want TS to accept only "id", "name" or "total" as items in the array.
}

My question is:

How can I type the enabledColumn field so it can be an array that can accept only the values ("id" | "name" | "total"), like an Union?

I found many answers on transforming a keyof in Union, but not the reverse case.

The columns field works similarly to what I want, but it's an object.


UPDATE 1:

The problem here is that VSCode is not recognizing Array or (keyof RowData)[] autocomplete options when I try to use it inside the array. Also, if I put an arbitrary string there, it doesn't give me an error (only "id", "name" and "total" would be acceptable in the example).

If I do it as a manual Union (like I did in the above example), it recognizes (see screenshots below):

When using keyof it does not provide the options

When using manual union type, it provides

1

There are 1 best solutions below

2
erisco On

The union of property names of A is simply keyof A.

type MyTableRowData = {
  id : string;
  name : string;
  total : number;
}

// keyof MyTableRowData = 'id' | 'name' | 'total'

type TableDef<RowData> = {
  // ...
  enabledColumns: (keyof RowData)[];
}