Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get type of a variable and create new instance of this type

Lets say I have a base class with some property dataItems which is array of DataItem:

export class BaseClass{
   dataItems:DataItems[];
}

Then I have several classes which extend BaseClass and their dataItems property is an array of some class which extends DataItems:

export class BetterClass extends BaseClass{
   dataItems:BetterDataItems[];
}

export class BestClass extends BaseClass{
   dataItems:BestDataItems[];
}

Now I want to add a method in BaseClass which creates dataItems and adds them to array. Would it be possible to do all of this in BaseClass? I need to create instance of BetterDataItems or BestDataItems, depending on the class used.

At the moment I simply added:

dataItemType: typeof DataItem; 

property to BaseClass and in each class extending BaseClass I override this variable with the proper data item type:

in BetterClass:

dataItemType: typeof BetterDataItem = BetterDataItem;

in BestClass:

dataItemType: typeof BestDataItem = BestDataItem;

And then, in BaseClass I do this:

var dataItem = new this.dataItemType();

This works fine but my question is - would it be possible to avoid having dataItemType property at all? Can I find a type of dataItems array and create a new instance then?

Thanks!

like image 636
zeroin Avatar asked Oct 13 '15 06:10

zeroin


People also ask

How do I get the instance of a type in C#?

GetType Method is used to find the type of the current instance. This method returns the instances of the Type class that are used for consideration. Syntax: public Type GetType ();

How do I create a new instance?

Answer. To create a new instance of an object, we use the "new" keyword. This keyword creates a new instance of an object, which we can then assign to a variable, or invoke methods. For example, to create a new StringBuffer object, we would use the new keyword in the following way.

How do you check if an object is an instance of a particular type?

Using isinstance() function, we can test whether an object/variable is an instance of the specified type or class such as int or list. In the case of inheritance, we can checks if the specified class is the parent class of an object. For example, isinstance(x, int) to check if x is an instance of a class int .

Why do we create instance of class in C#?

You declare an instance constructor to specify the code that is executed when you create a new instance of a type with the new expression. To initialize a static class or static variables in a non-static class, you can define a static constructor.


2 Answers

TypeScript 1.6 code:

class DataItems {

}

class BaseClass {
   dataItems:DataItems[];
   dataItemType: typeof DataItems = DataItems;
}

compiles to:

var DataItems = (function () {
    function DataItems() {
    }
    return DataItems;
})();
var BaseClass = (function () {
    function BaseClass() {
        this.dataItemType = DataItems;
    }
    return BaseClass;
})();

And you can see that type information for dataItems property is lost in BaseClass. That's how TypeScript compiler works. It does not support runtime checking. So answer to your question is no.


Your workaround with dataItemType: typeof BetterDataItem = BetterDataItem; works because you make the TypeScript compiler to add JS command: this.dataItemType = BetterDataItem; which can be used later.

like image 59
Martin Vseticka Avatar answered Oct 06 '22 11:10

Martin Vseticka


Option 1: You could override the method in each sub class...

export class BaseClass{
   dataItems:DataItem[];

   create() {
       this.dataItems.push(new DataItem());
   }
}

export class BetterClass extends BaseClass{
   dataItems:BetterDataItem[];

   create() {
       this.dataItems.push(new BetterDataItem());
   }
}

export class BestClass extends BaseClass{
   dataItems:BestDataItem[];

      create() {
       this.dataItems.push(new BestDataItem());
   }
}

Option 2: But if you introduce a generic base class, you can remove the need to define the dataItems property on each class and also create different instances.

type MyT = typeof DataItem;

export class GenericBaseClass<T extends DataItem> {
    dataItems:T[];

    constructor(private dataType: MyT) {

    }

    create() {
        this.dataItems.push(<T>new this.dataType())
    }

}

export class BaseClass extends GenericBaseClass<DataItem> {
   constructor() {
       super(DataItem);
   }
}

export class BetterClass extends GenericBaseClass<DataItem> {
   constructor() {
       super(BetterDataItem);
   }
}

export class BestClass extends GenericBaseClass<DataItem> {
   constructor() {
       super(BestDataItem);
   }
}
like image 33
Fenton Avatar answered Oct 06 '22 13:10

Fenton