从构造函数初始化 Typescript 类值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16793503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:04:47  来源:igfitidea点击:

Initializing Typescript class values from constructor

inheritanceconstructortypescript

提问by Quango

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 superconstructor 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);

采纳答案by Jude Fisher

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 isodd that the variables are only initialized in the JS after the call to super(). Maybe worth raising a work item on codeplex?

奇怪的是,变量调用后才初始化的JS super()。也许值得在 codeplex 上提出一个工作项目

Playground.

游乐场

回答by Corey Ford

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 });

回答by Rindra Parama

@JcFx

@JcFx

this variable test always undefined before it's value assigned.

这个变量 test 在它被赋值之前总是未定义的。

if(target[prop] !== undefined){

if(target[prop] !== undefined){

you might want to make this if statement always 'true', or use this instead:

您可能希望使 if 语句始终为“真”,或者使用它来代替:

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