Search code examples
javascripttypescripttype-inferencetype-assertion

TS: Array to object type conversion


I have the following value:

const MY_CONST = [
  {
    id: 1,
    name: "ITEM_1"
  },
  {
    id: 2,
    name: "ITEM_2"
  }
] as const;

I would like to reduce the value to a typed object, staying in the order as it was in MY_CONST

type ConvertedConst = {
    1: "ITEM_1";
    2: "ITEM_2";
}

I have tried the following:

type MyConstItem = (typeof MY_CONST)[number];
type ConvertedConst = Record<MyConstItem["id"], MyConstItem["name"]>;

const converted = MY_CONST.reduce<ConvertedConst>((acc, curr) => {
  acc[curr.id] = curr.name;
  return acc;
}, {});

But the type ends up being:

type ConvertedConst = {
    1: "ITEM_1" | "ITEM_2";
    2: "ITEM_1" | "ITEM_2";
}

I presume some generic approach should be taken but I'm lost a little bit. Thanks for any help provided!


Solution

  • The desired type can be achieved by mapping through the elements of the array as follows:

    type ConvertedConst = {
      [K in MyConst[number] as K['id']]: K['name'];
    };
    
    

    The crucial part is as K['id']. By this key remapping, we are telling typescript to use K['id'] as a key and the value is pretty straightforward: K['name'].

    type MyConst = typeof MY_CONST;
    
    // type ConvertedConst = {
    //   1: "ITEM_1";
    //   2: "ITEM_2";
    // }
    type ConvertedConst = {
      [K in MyConst[number] as K['id']]: K['name'];
    };
    

    playground