Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic and typeof T in the parameters

In TypeScript I can define the type of a variable as the type of a class. For example:

class MyClass { ... }

let myVar: typeof MyClass = MyClass;

Now I want to use this with a generic class, something like this:

class MyManager<T> {
    constructor(cls: typeof T) { ... }
    /* some other methods, which uses instances of T */
}

let test = new MyManager(MyClass); /* <MyClass> should be implied by the parameter */

So, I want to give my manager class another class (its constructor), because the manager needs to retreive static information associated with the class.

When compiling my code, it says that it cannot find name 'T', where my constructor is.

Any idea how to solve it?

like image 420
Simon Avatar asked Jul 11 '16 16:07

Simon


1 Answers

You can use this type of constructors: { new (): ClassType }.

class MyManager<T> {
    private cls: { new(): T };

    constructor(cls: { new(): T }) {
        this.cls = cls;
    }

    createInstance(): T {
        return new this.cls();
    }
}

class MyClass {}

let test = new MyManager(MyClass);
let a = test.createInstance();
console.log(a instanceof MyClass); // true

(code in playground)


Edit

The proper way to describe a class type in typescript is using the following:

{ new(): Class }

For example in the typescript lib.d.ts ArrayConstructor:

interface ArrayConstructor {
    new (arrayLength?: number): any[];
    new <T>(arrayLength: number): T[];
    new <T>(...items: T[]): T[];
    (arrayLength?: number): any[];
    <T>(arrayLength: number): T[];
    <T>(...items: T[]): T[];
    isArray(arg: any): arg is Array<any>;
    readonly prototype: Array<any>;
}

Here you have 3 different ctor signatures plus a bunch of static functions.
In your case you can also define it like:

interface ClassConstructor<T> {
    new(): T;
}

class MyManager<T> {
    private cls: ClassConstructor<T>;

    constructor(cls: ClassConstructor<T>) {
        this.cls = cls;
    }

    createInstance(): T {
        return new this.cls();
    }
}
like image 185
Nitzan Tomer Avatar answered Oct 30 '22 16:10

Nitzan Tomer