just.me
just.me

Reputation: 2285

Keep type structure of object

I have a function which transforms an object into another with very specific rules. I guess the following function can serve as an example:

interface SomethingWithAValue<T> {
  value: T;
}

function transform(obj) {
  let value = {};
  for(let key in obj) {
    value[key] = obj[key].value;
  }
  return { value };
}

This basically transforms an object of type (pseudocode)

{
  [key 1]: SomethingWithAValue<type 1>,
  [key 2]: SomethingWithAValue<type 2>,
  ...
  [key n]: SomethingWithAValue<type n>
}

into a new object of type (again pseudocode)

SomethingWithAValue<{
  [key 1]: type 1,
  [key 2]: type 2,
  ...
  [key n]: type n
}>

I still need to add a proper type declaration to transform, so what is the best approach here?

Upvotes: 0

Views: 50

Answers (1)

jcalz
jcalz

Reputation: 329553

Ah, you need mapped types and inference from mapped types.

Here's how you use a mapped type to represent the mapping from a regular object to one in which all the property values are wrapped in SomethingWithAValue<>:

type SomethingMapper<T> = {
  [K in keyof T]: SomethingWithAValue<T[K]>
}

type Example = {
  a: string,
  b: number
}
type SomethingMappedExample = SomethingMapper<Example>;
// { 
//   a: SomethingWithAValue<string>; 
//   b: SomethingWithAValue<number>; 
// }

And here's how you use inference from mapped types to type the function which unwraps:

function transform<T>(obj: SomethingMapper<T>): T {
  // implementation
}
declare let mappedExample: SomethingMappedExample;
const unwrapped: Example = transform(mappedExample); // okay

Hope that helps. Good luck!

Upvotes: 1

Related Questions