简体   繁体   English

从构造函数初始化Typescript类值

[英]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.

相关问题 通过基类构造函数从驱动类模板值初始化基类数组成员变量 - initializing base class array member variable via base class constructor from drived class template value 在派生类的构造函数中初始化超类 - Initializing superclass in derived class's constructor TypeScript类继承构造函数混淆 - TypeScript class inheritance constructor confusion 从C#中存储的缓存初始化构造函数 - Initializing constructor from stored cache in C# 模板 class 模板构造函数专门用于初始化模板化基础 class - Template class with template constructor specialization for initializing a templated base class 使用私有派生类的构造函数初始化基类的数据成员 - Initializing data members of base class using the constructor of privately derived class 为什么我们必须将值从派生类构造函数传递给基类构造函数 - Why do we have to pass values from derived class constructor to base class constructor 通过派生构造函数的参数初始化继承的类(C#) - Initializing Inherited Class Through Derived Constructor's Arguments (C#) 具有来自继承的抽象类的值的构造函数,该类实现一个接口 - Constructor with values from inherited abstract class, which implements an interface 基于类和子类属性的 Typescript 构造函数参数 - Typescript constructor parameters based on class & subclass properties
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM