2013-05-28 3 views
12

Я использую TypeScript для создания некоторых классов с помощью KnockoutJS, причем данные загружаются из некоторого JSON, возвращаемого WebAPI.Инициализация значений класса Typcript из конструктора

Проблема в том, что я хотел скопировать значения JSON в класс TypeScript из конструктора: но если я делаю это только в базовом классе, унаследованные свойства не определены и поэтому не инициализируются.

Пример

Мы хотим, чтобы создать элемент инвентаризации от ответа JSON:

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

У меня есть базовый класс продукт и унаследованный класс 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 
    } 
} 

свойства для Инвентарь создается только в выходном коде JS после вызова конструктора super, поэтому не существует, когда конструкция продукта или выполняется.

Единственное решение, которое я вижу, это взять инициализирующее значение из конструктора, но мне не очень нравится этот подход, хотя я подозреваю, что это единственный вариант.

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

Какова цель копирования свойств в базовый экземпляр? Плохо, если после копии указано количество и цена? – BSick7

+0

Я не уверен, что понимаю, в чем проблема. Конструктор 'Product' должен установить' Name' из 'source', а конструктор' Inventory' должен установить 'Quantity' и' Price' из 'source' – MiMo

+0

. Проблема в том, что вам нужно дважды вызвать свойства копирования: без разницы. Если вы только что сделали это в классе Product, это установит только Name. Если вы только сделали это в Inventory, вы не вызываете его в Product, поэтому ничего, что создает продукт, не будет инициализировано – Quango

ответ

8

Лучшее, что я могу придумать, чтобы позволить вам иметь базовые десериализации процедуру, которая вызывается из конструктора этого (изменено, чтобы удалить нокаут зависимость для тестирования):

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

это является странным, что переменные инициализируются только в JS после вызова super(). Может стоить raising a work item on codeplex?

Playground.

+0

Спасибо за предложение: наличие такого инициализатора - хорошая альтернатива. Я не думаю, что это ошибка в TypeScript, так как я ожидаю, что она будет работать так, как она есть. Это динамичный характер JS: нет метаданных и размышлений для работы, в отличие от C# и т. Д. – Quango

+0

Согласовано. Странность, а не ошибка. – JcFx

3

Этого подход, кажется, работает для меня:

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

Спасибо .. это тоже сработает, но как только вы начнете добавлять много переменных, это делает для утомительной кодировки. Сначала я попробую идею JcFX – Quango

Смежные вопросы