I'm using TypeScript to create some classes with KnockoutJS, with the data being loaded from some JSON returned by WebAPI.
The problem is I wanted to copy the JSON values into my TypeScript class from the constructor: but if I do this just at the base class, the inherited properties have not been defined and so are not initialised.
Example
We want to create an inventory item from a JSON response:
{ Name: "Test", Quantity:1, Price: 100 }
I have a base class Product and an inherited class Inventory:
export class Product {
Name = ko.observable("");
constructor(source) {
// a utility that copies properties into this instance
utils.CopyProperties(source,this);
}
export class Inventory extends Product {
Quantity = ko.observable(0);
Price = ko.observable(0);
constructor(source) {
super(source); // call base c'tor
// the quantity and price properties are only now defined
}
}
The properties for Inventory are only created in the JS output code after the super constructor call, so do not exist when the Product constructor is executed.
The only solution I can see is to take the initialising value out of the constructor, but I don't really like this approach, although I suspect it's the only option.
var inventoryItem = new Inventory();
inventoryItem.LoadFrom(source);
Best I can come up with to allow you to have a base deserialization routine that is called from the constructor is this (modified to remove knockout dependency for testing):
class utils {
public static CopyProperties(source:any, target:any):void {
for(var prop in source){
if(target[prop] !== undefined){
target[prop] = source[prop];
}
else {
console.error("Cannot set undefined property: " + prop);
}
}
}
}
class Product {
Name = "Name";
constructor(source) {
this.init(source);
}
init(source){
utils.CopyProperties(source,this);
}
}
class Inventory extends Product {
Quantity;
Price;
constructor(source) {
super(source);
}
init(source){
this.Quantity = 0;
this.Price = 0;
super.init(source);
}
}
var item = new Inventory({ Name: "Test", Quantity: 1, Price: 100 });
It is odd that the variables are only initialized in the JS after the call to super()
. Maybe worth raising a work item on codeplex?
Playground.
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