Jeanluca Scaljeri
Jeanluca Scaljeri

Reputation: 29107

Generically type a class using a generically typed interface

This is a pure Typescript/Generics question. The source of my question originates from the Angular/CDK (portal.d.ts):

/** Interface that can be used to generically type a class. */
export interface ComponentType<T> {
    new (...args: any[]): T;
}

I'm trying to wrap my head around this one, without much luck so far. The problem can be seen from the test code I wrote to understand this:

export interface ComponentType<T> {
    new (...args: any[]): T;
}

interface Bar<T> {
    getData: () => T
}

class MyBooleanComponent implements Bar<boolean> {
    getData(): boolean { return true; }
}


class MyGenericWrapper {
    init<T>(comp: ComponentType<T>): T {
        return new comp();
    }
}

const wrapper = new MyGenericWrapper();
const instance = wrapper.init<boolean>(MyBooleanComponent);

(instance as Bar).getData();

CODE

enter image description here

As can be seen there are some problems with this code.

First, MyBooleanComponent, which is not assignable to ComponentType<boolean>. Its unclear to me how I can tell that MyBooleanComponent` returns booleans?

Second, if I cast (instance as Bar).getData(); the typescript compiler is unhappy with Bar, it wants (instance as Bar<boolean>).getData(); but I would expect based on how I initialized/setup the whole thing it should be possible derive the boolean right?

I'm not use if I'm doing something just wrong or maybe trying to do the impossible. Any help would be appreciated!

Upvotes: 1

Views: 56

Answers (1)

MJ_Wales
MJ_Wales

Reputation: 893

I think the confusion is that type T in MyGenericWrapper is different to type T in interface Bar. You have set interface Bar's generic type to boolean by MyBooleanComponenet:

class MyBooleanComponent implements Bar<boolean> {
    getData(): boolean { return true; }
}

Where as MyGenericWrapper's generic type is set to MyBooleanComponent

const wrapper = new MyGenericWrapper();
const instance = wrapper.init<MyBooleanComponent>(MyBooleanComponent);
instance.getData();

Working example.

Upvotes: 1

Related Questions