2013-05-28 14 views
12

Używam TypeScript do tworzenia klas z KnockoutJS, z danymi ładowanymi z niektórych JSON zwróconych przez WebAPI.Inicjowanie wartości klasy maszynopisu z konstruktora

Problem polega na tym, że chciałem skopiować wartości JSON do mojej klasy TypeScript z konstruktora: ale jeśli zrobię to tylko w klasie bazowej, odziedziczone właściwości nie zostały zdefiniowane, a więc nie są inicjowane.

Przykład

Chcemy stworzyć element inwentaryzacji z odpowiedzi JSON:

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

Mam klasy bazy produktowej oraz dziedziczone klasy zapasy:

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

właściwościach Zapasy są tworzone tylko w kodzie wyjściowym JS po wywołaniu konstruktora super-, więc nie istnieją, gdy konstrukcja produktu lub jest wykonywany.

Jedyne rozwiązanie, jakie widzę, to odebranie wartości inicjalizacyjnej konstruktorowi, ale nie podoba mi się to podejście, chociaż podejrzewam, że jest to jedyna opcja.

var inventoryItem = new Inventory(); 
    inventoryItem.LoadFrom(source); 
+0

Jaki jest cel kopiowania właściwości do instancji podstawowej? Czy to źle, jeśli ilość i cena są zdefiniowane po kopii? – BSick7

+0

Nie jestem pewien, czy rozumiem, jaki jest problem. Konstruktor 'produktu' powinien ustawić' Name' z 'source', a konstruktor' Inventory' powinien ustawić 'Quantity' i' Price' from 'source' – MiMo

+0

Problem polega na tym, że musisz dwukrotnie wywołać właściwości kopiowania: nie ma sensu. Jeśli właśnie zrobiłeś to w klasie Produkt, ustawiłaby tylko Nazwę. Jeśli zrobiłeś to tylko w Ekwipunku, nie wywołujesz go w Produkcie, więc wszystko, co tworzy produkt, nie zostanie zainicjowane. – Quango

Odpowiedz

8

Najlepszy mogę wymyślić, co pozwala mieć rutynę baza deserializacjia, która jest wywoływana z konstruktora jest to (zmodyfikowane w celu usuwania nokaut zależność do testowania):

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

to jest dziwne, że zmienne są inicjowane tylko w JS po wywołaniu super(). Może warto raising a work item on codeplex?

Playground.

+0

Dzięki za sugestię: posiadanie takiego inicjatora jest dobrą alternatywą. Nie sądzę, żeby to był błąd w TypeScript, ponieważ spodziewałbym się, że będzie działał tak, jak robi. Jest to dynamiczna natura JS: nie ma metadanych i refleksji do pracy, w przeciwieństwie do C# itd. – Quango

+0

Uzgodnione. Dziwactwo, a nie błąd. – JcFx

3

Takie podejście wydaje się działać dla mnie:

/// <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 }); 
+0

Dzięki .. to też zadziała, ale gdy zaczniesz dodawać wiele zmiennych, będzie to żmudne kodowanie. Spróbuję najpierw pomysłu JcFX – Quango

Powiązane problemy