A generic type is like a template. You cannot create instances of it unless you specify real types for its generic type parameters. To do this at run time, using reflection, requires the MakeGenericType method.
Like C++, we use <> to specify parameter types in generic class creation. To create objects of a generic class, we use the following syntax. Note: In Parameter type we can not use primitives like 'int','char' or 'double'.
Cannot Instantiate Generic Types with Primitive Types. Cannot Create Instances of Type Parameters.
Syntax. var object_name = { key1: “value1”, //scalar value key2: “value”, key3: function() { //functions }, key4:[“content1”, “content2”] //collection }; As shown above, an object can contain scalar values, functions and structures like arrays and tuples.
To create a new object within generic code, you need to refer to the type by its constructor function. So instead of writing this:
function activatorNotWorking<T extends IActivatable>(type: T): T {
return new T(); // compile error could not find symbol T
}
You need to write this:
function activator<T extends IActivatable>(type: { new(): T ;} ): T {
return new type();
}
var classA: ClassA = activator(ClassA);
See this question: Generic Type Inference with Class Argument
Because the compiled JavaScript has all the type information erased, you can't use T
to new up an object.
You can do this in a non-generic way by passing the type into the constructor.
class TestOne {
hi() {
alert('Hi');
}
}
class TestTwo {
constructor(private testType) {
}
getNew() {
return new this.testType();
}
}
var test = new TestTwo(TestOne);
var example = test.getNew();
example.hi();
You could extend this example using generics to tighten up the types:
class TestBase {
hi() {
alert('Hi from base');
}
}
class TestSub extends TestBase {
hi() {
alert('Hi from sub');
}
}
class TestTwo<T extends TestBase> {
constructor(private testType: new () => T) {
}
getNew() : T {
return new this.testType();
}
}
//var test = new TestTwo<TestBase>(TestBase);
var test = new TestTwo<TestSub>(TestSub);
var example = test.getNew();
example.hi();
All type information is erased in JavaScript side and therefore you can't new up T just like @Sohnee states, but I would prefer having typed parameter passed in to constructor:
class A {
}
class B<T> {
Prop: T;
constructor(TCreator: { new (): T; }) {
this.Prop = new TCreator();
}
}
var test = new B<A>(A);
export abstract class formBase<T> extends baseClass {
protected item = {} as T;
}
Its object will be able to receive any parameter, however, type T is only a typescript reference and can not be created through a constructor. That is, it will not create any class objects.
I know late but @TadasPa's answer can be adjusted a little by using
TCreator: new() => T
instead of
TCreator: { new (): T; }
so the result should look like this
class A {
}
class B<T> {
Prop: T;
constructor(TCreator: new() => T) {
this.Prop = new TCreator();
}
}
var test = new B<A>(A);
I was trying to instantiate the generic from within a base class. None of the above examples worked for me as they required a concrete type in order to call the factory method.
After researching for awhile on this and unable to find a solution online, I discovered that this appears to work.
protected activeRow: T = {} as T;
The pieces:
activeRow: T = {} <-- activeRow now equals a new object...
...
as T; <-- As the type I specified.
All together
export abstract class GridRowEditDialogBase<T extends DataRow> extends DialogBase{
protected activeRow: T = {} as T;
}
That said, if you need an actual instance you should use:
export function getInstance<T extends Object>(type: (new (...args: any[]) => T), ...args: any[]): T {
return new type(...args);
}
export class Foo {
bar() {
console.log("Hello World")
}
}
getInstance(Foo).bar();
If you have arguments, you can use.
export class Foo2 {
constructor(public arg1: string, public arg2: number) {
}
bar() {
console.log(this.arg1);
console.log(this.arg2);
}
}
getInstance(Foo, "Hello World", 2).bar();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With