Home > Software design >  How to map an array of object property names to an array of the values that the names point to in a
How to map an array of object property names to an array of the values that the names point to in a

Time:10-10

const obj = { wheels: 4, lights: 2, doors: 4 }

someMapFunction(obj, { 
  props: ["wheel", "lights"], 
  format: (wheels, lights) => `${wheels}-${lights}`
})

How would I type someMapFunction so that typescript knows that props can only be keys of obj and that the format function will take all of the values that the props array values point to within obj?

CodePudding user response:

You would define the function like this:

function someMapFunction<
  T, 
  K extends (keyof T)[]
>(obj: T, propsAndFormat: { 
  props: [...K], 
  format: (...args: {
    [I in keyof K]: T[K[I]]
  }) => string 
}) {
  return null!
}

It has two generic parameters T and K. T describes the type of the object passed as obj while K is a tuple of keys of T. When we declare the parameter type of props, we use the variadic tuple syntax [...K] to infer K as a tuple and not and array since the order is important.

For format, we declare it to be a rest parameter where the order and type of elements are described by a tuple. To create this tuple, we can map over the elements I in the tuple K and use them to extract the corresponding type of T.


Playground

CodePudding user response:

Tobias' answer is right, I would just do it somewhat differently. I would make the type T extend a Record since you are dealing with objects. And I don't think you need to use a tuple.

type PropsAndFormat<T> = {
  props: keyof T;
  format: (...keys: string[]) => string;
};

function someMapFunction<T extends Record<string, unknown>>(
  obj: T,
  { props, format }: PropsAndFormat<T>,
): string {
  //
}
  • Related