Home > OS >  TypeScript: Convert Array to Object
TypeScript: Convert Array to Object

Time:09-27

I am trying to write a generic type for a function which converts array to object as below:

type ObjType = { id: number; name: string; status: string };
const zzx: ObjType[] = [
  {
    id: 1,
    name: "A",
    status: "a"
  },
  {
    id: 2,
    name: "B",
    status: "b"
  },
  {
    id: 3,
    name: "C",
    status: "c"
  }
];

function arrayToObject<T>(
  arr: T[],
  key: string | number
): Record<string | number, T> {
  const result: Record<string, T> = {};
  for (const item of arr) {
    const value = item[key as keyof typeof T];
    result[value] = item;
  }
  return result;
}

const xx = arrayToObject<ObjType>(zzx, "id");

I have read somewhere that generic types could be passed as params in <> brackets. But, I am not seeing the type (ObjType) in the function which I am passing from the function call. And also getting below error in line item[key as keyof typeof T];

Element implicitly has an 'any' type because expression of type 'string | number | symbol' can't be used to index type 'unknown'.
  No index signature with a parameter of type 'string' was found on type 'unknown'.

Can someone please tell what am I doing wrong?

CodePudding user response:

When passing the Generic type parameter, it'd check your usage, not the Generic type implementation, i.e. the usage of a type doesn't matter at all in validating the type itself!

You may customize your Generic type a bit to get something that works fine, And remember, there's no one correct solution, it always depends on your needs!

Check out this possible solution

first, for simplicity, I've added these types

type KType = string | number
type GeneratedObj<T> = Record<KType, T>

Note that you are returning result so it should be the same type of the function return type

for the function type, I've changed it to:

function arrayToObject<T extends Record<KType, unknown>>(
  arr: T[],
  key: KType
): GeneratedObj<T> {
...
...

You are expecting T to have a key that should be used in a place where you need to pass a string or a number, then you can just tell typescript that information, that this T extends this shape, an object that has a key of type string | number, Regarding value, you can type it if you know its type, if it can be anything you can leave it as unknown

now you can directly do:

const value = item[key];

but because the value of T props is defined now as unknown we need to cast the type of value in the next line:

result[value as KType] = item;
  • Related