Cameron Bell Cameron Bell - 23 days ago 7
TypeScript Question

Typescript/Javascript parsing a class type as function paramter

I want to write a function where you parse the class type (the class, not an instance) then the function will instantiate an instance based on that parameter.

This is best explained by example:

//All possible paramter types must inherit from this base class
class Base { public name : string = ''; }

//These are possible classes that could be parsed to the function
class Foo extends Base { constructor() { super(); console.log("Foo instance created"); } }
class Bar extends Base { constructor() { super(); console.log("Bar instance created"); } }

//This function should take a class that inherits from 'Base' as a paramter - then it will create an instance
function Example(param : ?????????) : Base //I don't know what type the 'param' should be
{
return new param(); //Create instance?? How do I do this
}

//This should be the output - if it worked (but it doesn't)
Example(Foo); //Logs "Foo instance created""
Example(Bar); //Logs "Foo instance created""

//So if this worked, it would become possible to do this:
let b : Foo = Example(Foo);
let c : Bar = Example(Bar);


So my questions is: what type would the param for the 'Example' function be? And how would I create an instance of param from within the function.

Note, if this question is a duplicate I apologise - but I don't know the technical name for this process so it is difficult to research.

Answer

You want something like this.

function Example<T extends Base>(param: new () => T): T {
    return new param();
}

We know that you'll have some type that is a Base. We're going to name it T, and we'll say that T extends Base to enforce that.

We also know that param will construct a T with no parameters. We can write new () => T to describe that.


Basically the way to think about this is that a class has both an instance side and a static side (also called the "constructor" side). In your example, Base, Foo, and Bar on their own have the static side.

The static side for each of them consists of all the static members you specify (and there aren't any in this case), along with the construct signature. In your case, Example takes a constructor expects no arguments, and produces some subtype of Base.