Search code examples
typescriptmapped-types

transform object member type depending on the original type


In an object, I want to transform each member's type to another depending on the said member variable.

Here is an exemple:

class A {
    fct = (): string => 'blabla';
}

class B {
    fct = (): number => 1;
}

class C {
    fct = (): { obj: string } => ({
        obj: 'la'
    });
}

export const Contracts = {
    a: A,
    b: B,
    c: C
};

type myContracts = typeof Contracts;

type MySuperType<T> = {
    [P in keyof T]: string;
};

type a = MySuperType<myContracts>;

The snipped above gives:

type a = {
    a: string;
    b: string;
    c: string;
}

What I want:

type a = {
    a: string;
    b: number;
    c: { obj: string };
}

Solution

  • Make MySuperType require that the values on the object satisfy a class whose instances have a fct property that's a function. Take the InstanceType of the class to get the instance, then use ReturnType to get the returned type for each such instance.

    type FctClass = {
      new(): { fct: (...args: unknown[]) => unknown}
    }
    type MySuperType<T extends Record<string, FctClass>> = {
        [P in keyof T]: ReturnType<InstanceType<T[P]>['fct']>;
    };
    
    type a = MySuperType<myContracts>;