Nik*_*Nik 8 javascript decorator typescript ecmascript-next
我正在构建前端/后端数据结构之间的简单映射.为了做到这一点,我创建了一个看起来如下的装饰器:
function ApiField(
apiKey: string,
setFn: (any) => any = (ret) => ret,
getFn: (any) => any = (ret) => ret
) {
return function (target: AbstractModel, propertyKey: string) {
target.apiFieldsBag = target.apiFieldsBag || {};
_.assign(
target.apiFieldsBag,
{
[propertyKey]: {
apiKey: apiKey,
setFn: setFn,
getFn: getFn
}
}
);
};
}
Run Code Online (Sandbox Code Playgroud)
这就是我使用它的方式:
class AbstractCar {
@ApiField('id')
public id: string = undefined;
}
class BMW extends AbstractCar {
@ApiField('cylinders')
public cylinderCount: number;
}
class VW extends AbstractCar {
@ApiField('yearCompanyFounded')
public yearEstablished: number;
}
Run Code Online (Sandbox Code Playgroud)
我看到的问题是,而不是传递给装饰器的实际对象,它始终是它的原型:
__decorate([
ApiField('yearCompanyFounded')
], VW.prototype, "yearEstablished", void 0);
Run Code Online (Sandbox Code Playgroud)
这意味着当我将东西分配给装饰器中的实例时,它总是附加到原型上,这反过来意味着我想要定义的属性只有VW实例AbstractCar在BMW类和类上也可用(在这个例子中这将是be yearEstablished).这使得不可能在两个不同的类中具有两个具有相同名称但不同API字段的属性.
有没有办法规避这种行为?
现在,所有三个类都向同一个对象添加属性。解决此问题的关键是克隆对象,target.data以便每个类都使用不同的对象,而不是所有类都引用同一对象。
这是一个更简单的示例,演示了执行此操作的一种方法:
function ApiField(str: string) {
return function (target: any, propertyKey: string) {
// I tested with Object.assign, but it should work with _.assign the same way
target.data = _.assign({}, target.data, {
[propertyKey]: str
});
};
}
class AbstractCar {
@ApiField("car")
public carID;
}
class BMW extends AbstractCar {
@ApiField("bmw")
public bmwID;
}
class VW extends AbstractCar {
@ApiField("vw")
public vwID;
}
AbstractCar.prototype.data; // Object {carID: "car"}
BMW.prototype.data; // Object {carID: "car", bmwID: "bmw"}
VW.prototype.data; // Object {carID: "car", vwID: "vw"}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
515 次 |
| 最近记录: |