Typescript: How to wrap interface properties?

Suppose I have the following definitions:

interface ISomeInterface {
  propertyA: string,
  propertyB: number,
  propertyC: boolean,
  propertyD: ISomeOtherInterface // bonus points for this one!
}

class MyGeneric<T> {}
class MyGenericContainer<T> {}

now I want to "wrap" all properties, so that I recieve something like that:

interface ISomeWrappedInterface {
  propertyA: MyGeneric<string>,
  propertyB: MyGeneric<number>,
  propertyC: MyGeneric<boolean>,
  propertyD: MyGenericContainer<ISomeOtherInterface>
}

Note: PropertyD is probably impossible, but in case the property type is not some "primitive", I simply want it to be wrapped by another class

This is as far as I have gotten:

type FromInterface<I> = ({
  [T in keyof I]: MyGeneric<typeof T>;
                                   ^--------
});

type Wrapped = FromInterface<ISomeInterface>;

But this does not work, because 'T' only refers to a type, but is being used as a value here.
I guess it’s because T already is a type here, but obviously I want the "widened" type of the property that I am iterating.

Disclaimer: I’ve found this question, seems similar, but isn’t.

>Solution :

You can use:

  • mapped type to transform each proprerty in the input type
  • conditional type to select output property type depending on some condition
type FromInterface<T> = {
  [K in keyof T]: T[K] extends string | number | Date 
                  ? MyGeneric<T[K]> 
                  : MyGenericContainer<T[K]>;                            
};

Playground link

Leave a Reply