通过typescript类

时间:2016-03-14 13:25:02

标签: javascript angularjs typescript prototype angular-http

  

tl; dr:我需要将已编译的Typescript原型定义应用于我已定义为该类的对象。

情况: 我需要通过typescript类中定义的一些业务逻辑来扩展JavaScript对象 这可能看起来像:

class Address
{
  constructor(
    public Street: string,
    public Number: number,
    public Zip: number,
    public City: string)
  { }

  public get FullAddress()
  {
    return this.Street + ' ' + this.Number + ', '
      + this.Zip + ' ' + this.City;
  }
}

编译后的JS添加了用FullAddress扩展对象原型的代码。如果我打电话给new Address('Somestreet', 5, 3564, 'SomeCity'),一切都像魅力一样。

问题:当我得到一些JS对象时(在我的情况下使用angular $http

$http.get('/api/address').then((answer: AngularPromise<Address[]>) => 
{
  console.log(answer.data[0].FullAddress());
});

我可以在对象上调用函数FullAddress,因为在Typescript中,函数是在类定义上定义的。

现在当我在浏览器中执行代码answer.data.FullAddress()时没有定义(这是有道理的,因为Typescript只提供了类型定义而从未触及过对象。

尝试解决方案:一种可能的解决方案是为每个对象调用构造函数(有点像跟随)

$http.get('/api/address').then((answer: AngularPromise<Address[]>) => 
{
  for(var i = 0; i < answer.data.length; i++)
  {
    answer.data[0] = new Address(answer.data[0].Street, ans.....);
  }
  console.log(answer.data[0].FullAddress());
});

并且可能重载Address构造函数以接受整个对象以减少样板。

实际问题:由于我需要的对象是比这里描述的简单地址构造更复杂的嵌套结构,上面的解决方案需要我写出大量的样板文件,我觉得必须有一个更好的解决方案来解决这个问题。

1 个答案:

答案 0 :(得分:0)

有同样的问题!一种方法,正如你所说的那样,建立一个构造函数并提供所有信息 - 有点单调乏味,似乎是错误的。我们最终创建了一个MapTo函数,可以将通用对象映射到强类:

public static MapTo(jsonObject, nameSpace, classType) {
    var instance = new classType();
    for (var prop in jsonObject) {
        if (!jsonObject.hasOwnProperty(prop)) {
            continue;
        }

        if (jsonObject[prop] == null) {
            instance[prop] = null;
        } else if (typeof jsonObject[prop] === 'object') {
            if (nameSpace[prop]) {
                instance[prop] = this.MapTo(jsonObject[prop], nameSpace, nameSpace[prop]);
            } else {
                instance[prop] = jsonObject[prop];
            }
        } else {
            instance[prop] = jsonObject[prop];
        }
    }

    return instance;
}

用法是:

var strongAddress = MapTo(answer.data[0], Models, Models.Address); //I assumed your class was in a namespace called "Models"