peterjwest
peterjwest

Reputation: 4452

How can preserve the types for a mapped object in Typescript

If I have a dictionary object such as:

const x = {
  foo: {inner: 3},
  bar: {inner: 'hi'},
};

Where there is an inner property with varying type (string and number here for example).

Then I would like to map this to a structure which looks like:

const y = {
  foo: 3,
  bar: 'hi',
};

However I'd like to be able to do this automatically without losing any type information. Is this possible in Typescript?

I can almost get there with lodash:

import { mapValues } from 'lodash';
const y: Y = mapValues(x, (z) => z.inner);

However this ends up taking the union of all types in the dictionary, with the type signature:

const y: {
    foo: string | number;
    bar: string | number;
}

Rather than the desired:

const y: {
  foo: number;
  bar: string;
};

Upvotes: 4

Views: 1146

Answers (1)

dbandstra
dbandstra

Reputation: 1314

Something like this should work:

type Wrapped<T> = {[K in keyof T]: {inner: T[K]}};

function unwrap<T>(x: Wrapped<T>): T {
  // (the implementation here is not the point)
  return _.mapValues(x as any, z => z.inner) as T;
}

const y = unwrap(x);

Reference: https://www.typescriptlang.org/docs/handbook/advanced-types.html (the very last paragraph)

Upvotes: 5

Related Questions