it-swarm.com.de

TypeScript-Klassenwerte werden vom Konstruktor initialisiert

Ich verwende TypeScript, um einige Klassen mit KnockoutJS zu erstellen, wobei die Daten aus einem von WebAPI zurückgegebenen JSON geladen werden.

Das Problem ist, dass ich die JSON-Werte vom Konstruktor in meine TypeScript-Klasse kopieren wollte. Wenn ich dies jedoch nur bei der Basisklasse mache, wurden die geerbten Eigenschaften nicht definiert und daher nicht initialisiert.

Beispiel

Wir möchten aus einer JSON-Antwort ein Inventarelement erstellen:

{ Name: "Test", Quantity:1, Price: 100 }

Ich habe eine Basisklasse Produkt und eine vererbte Klasse Inventar:

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

Die Eigenschaften für Inventory werden nur im JS-Ausgabecode nach dem Konstruktoraufruf super erstellt. Sie sind also nicht vorhanden, wenn der Produktkonstruktor ausgeführt wird.

Die einzige Lösung, die ich sehen kann, ist, dem Konstruktor den Initialisierungswert zu entnehmen, aber ich mag diesen Ansatz nicht wirklich, obwohl ich vermute, dass dies die einzige Option ist.

  var inventoryItem = new Inventory();
  inventoryItem.LoadFrom(source);
13
Quango

Am besten kann ich mir einfallen lassen, damit Sie eine grundlegende Deserialisierungsroutine haben, die vom Konstruktor aufgerufen wird (hier modifiziert, um die Knockout-Abhängigkeit zum Testen zu entfernen):

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

ist odd, dass die Variablen erst nach dem Aufruf von super() in der JS initialisiert werden. Vielleicht wert ein Arbeitselement über Codeplex anheben ?

Spielplatz .

11
Jude Fisher

Dieser Ansatz scheint für mich zu funktionieren:

/// <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 });
3
Corey Ford

@JcFx

diese Variable test ist immer undefiniert, bevor ihr Wert zugewiesen wird.

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

sie können diese if-Anweisung immer als "true" definieren oder stattdessen diese verwenden:

for (const prop of Object.keys(source)) {
  this[prop] = source[prop];
}

es geht um Forin, siehe diesen Link: https://github.com/angular/tsickle/issues/125

0
Rindra Parama