Typescript动态类方法

时间:2015-07-08 21:22:39

标签: typescript

问题

如何将类型检查添加到动态创建的类方法中?

实施例

给出一个非常简单的Property类。

class Property {
  value: any;
  name: string;

  constructor(name: string, value: any) {
    this.name = name;
    this.value = value
  }
}

Entity

class Entity {
  name: string;
  properties: Property[];


  constructor(name: string, properties: Property[]) {
    this.name = name;
    this.properties = properties;

    this.properties.forEach((p: Property, index: number) => {
      this[p.name] = (value: string): any => {
        if (value) {
          this.properties[index].value = value;
        }
        return this.properties[index].value;
      }
    }, this);
  }
}

重要部分:this[p.name] = function ...(我们不知道"方法的名称和#34;时间)。

转换为javascript时出现以下错误:

var car = new domain.Entity(
  'car',
  [
    new domain.Property('manufacturer', 'Ford'),
    new domain.Property('model', 'Focus')
  ]
);

car.model() // error TS2339: Property 'model' does not exist on type 'Entity'.

我知道这是一种不常见的类使用,因为Entity的不同实例将定义不同的方法。有没有办法摆脱错误,即打字稿能够识别每个实例的正确接口,或者至少沉默错误

备注

这是有效的javascript,可以通过以下方式使用它:

var car = new domain.Entity(
  'car',
  [
    new domain.Property('manufacturer', 'Ford'),
    new domain.Property('model', 'Focus')
  ]
);

car.model()          // 'Focus'
car.model('Transit') // 'Transit'

我知道这已在similar question上被询问,但这种情况略有不同,因为方法名称也是在运行时定义的。

2 个答案:

答案 0 :(得分:0)

添加此类型(只需一次):

interface Prop<T> {
    (): T;
    (value: T): T;
}

然后你可以为你创建的每个形状写这个:

interface Car extends Entity {
    model: Prop<string>;
    manufacturer: Prop<string>;
}
let car = <Car>new Entity('car', [/*...*/]);
car.model(32); // Error
let x = car.model(); // x: string

答案 1 :(得分:0)

如果您要访问动态属性,请使用任意类型来绕过变量的类型检查。您可以使用get go中的 any 类型声明变量,或者稍后使用类型断言运算符( as )。所以这里有一些可能的变种:

var car: any = new domain.Entity(...);
car.model();

var car = new domain.Entity(...) as any;
car.model();

var car = new domain.Entity(...);
(car as any).model();