How can I make the following work as expected in Typescript?
export class ProxyObject<T> {
private _dataObject:T;
constructor(dataObject?:T) {
if (dataObject) {
this.dataObject = dataObject;
} else {
//create a new instance of the generic <T> here
this.dataObject = <T> new Object();
}
}
set dataObject(dataObject:T) {
this._dataObject = dataObject;
}
get dataObject():T {
return this._dataObject;
}
}
export class ClassA {
myCoolProperty = "My Cool Property";
}
When I do the following:
export class MyObject extends ProxyObject<ClassA> {
}
And then:
var obj = new MyObject();
obj.dataObject.myCoolProperty === undefined
None of the ClassA properties or functions exist on the dataObject inside the MyObject as I was expecting. For instance, I expected dataObject to have myCoolProperty.
I'm trying to write a ProxyObject class that when extended it's DataObject storage is typed as the generic.
Thanks!!
TypeScript supports generic classes. The generic type parameter is specified in angle brackets after the name of the class. A generic class can have generic fields (member variables) or methods. In the above example, we created a generic class named KeyValuePair with a type variable in the angle brackets <T, U> .
To specify generic object type in TypeScript, we can use the Record type. const myObj: Record<string, any> = { //... }; to set myObj to the Record type with string keys and any type for the property values.
Like C++, we use <> to specify parameter types in generic class creation.
Since typescript generics are implemented using type erasure T is not present at runtime, you can however pass the class in as a parameter to the base class constructor and then use it to create the new object.
export class DataObjectBase {
}
export class ProxyObject<T extends DataObjectBase> {
private _dataObject: T;
constructor(dataObject?: T, cls?: typeof DataObjectBase) {
if (dataObject) {
this.dataObject = dataObject;
} else {
//create a new instance of the generic <T> here
this.dataObject = <T> new cls();
}
}
set dataObject(dataObject: T) {
this._dataObject = dataObject;
}
get dataObject(): T {
return this._dataObject;
}
}
export class ClassA {
myCoolProperty = "My Cool Property";
}
export class MyObject extends ProxyObject<ClassA> {
public constructor(dataObject?: ClassA) {
super(dataObject, ClassA);
}
}
new MyObject();
obj.dataObject.myCoolProperty !== undefined
This approach still requires a bit of code in the derived classes but at least it keeps all of the logic in the base class
The class DataObjectBase is necessary since if I would have used typeof Object instead, ClassA could not have fulfilled the signarure of the Object class (as in ClassA doesn't have the constructors Object has). DataObjectBase is a class with a single constructor with no arguments, which ClassA, although not explicitly deriving from it, fulfills.
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