[英]Initializing Typescript class values from constructor
I'm using TypeScript to create some classes with KnockoutJS, with the data being loaded from some JSON returned by WebAPI. 我正在使用TypeScript创建一些使用KnockoutJS的类,其中的数据是从WebAPI返回的一些JSON加载的。
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. 问题是我想从构造函数中将JSON值复制到我的TypeScript类中:但是如果我只是在基类上执行此操作,则尚未定义继承的属性,因此不会初始化。
Example 例
We want to create an inventory item from a JSON response: 我们想要从JSON响应中创建一个库存项目:
{ Name: "Test", Quantity:1, Price: 100 }
I have a base class Product and an inherited class Inventory: 我有一个基类Product和一个继承的类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. Inventory的属性仅在超级构造函数调用之后在JS输出代码中创建,因此在执行Product构造函数时不存在。
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()
. 奇怪的是 ,该变量调用后才初始化的JS
super()
Maybe worth raising a work item on codeplex ? 也许值得在codeplex上提出一个工作项 ?
Playground . 游乐场 。
This approach seems to work for me: 这种方法似乎对我有用:
/// <reference path="knockout.d.ts" />
export class Product {
Name: KnockoutObservableString;
constructor(source) {
this.Name = ko.observable(source.Name);
}
}
export class Inventory extends Product {
Quantity: KnockoutObservableNumber;
Price: KnockoutObservableNumber;
constructor(source) {
super(source);
this.Quantity = ko.observable(source.Quantity);
this.Price = ko.observable(source.Price);
}
}
var item = new Inventory({ Name: "Test", Quantity: 1, Price: 100 });
@JcFx @JcFx
this variable test always undefined before it's value assigned. 此变量测试在分配值之前始终未定义。
if(target[prop] !== undefined){
you might want to make this if statement always 'true', or use this instead: 你可能想让这个if语句总是'true',或者使用它代替:
for (const prop of Object.keys(source)) {
this[prop] = source[prop];
}
it's about forin, see this link: https://github.com/angular/tsickle/issues/125 这是关于forin,请看这个链接: https : //github.com/angular/tsickle/issues/125
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.