[英]Adding properties to a class via decorators in TypeScript
在 TypeScript 的装饰器参考页面上,有一段代码片段说明了如何使用类装饰器覆盖构造函数:
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
@classDecorator
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
console.log(new Greeter("world"));
并在日志中:
class_1 {
property: 'property',
hello: 'override',
newProperty: 'new property' }
到目前为止,一切都很好。 但是尝试通过点符号访问newProperty
失败:
类型“Greeter”上不存在属性“newProperty”。ts(2339)
错误并且它没有在 VS Code 的提示中列出。 可以通过括号表示法访问它,但 TS 警告说
元素隐式具有“任何”类型,因为类型“Greeter”没有索引签名。ts(7017)
我错过了什么吗? 如何以类型安全的方式通过装饰器添加新属性? 我想像普通的类成员一样拥有普通的编译器支持。
设计的装饰器不能改变类的类型。 这仍在讨论中,并且在装饰器提案最终确定之前, 团队似乎不会改变行为。 你可以使用 mixins 来完成这个任务(阅读ts 中的 mixins )
使用 mixins 的代码看起来像:
function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
const Greeter = classDecorator(class {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
});
type Greeter = InstanceType<typeof Greeter> // have the instance type just as if we were to declare a class
console.log(new Greeter("world").newProperty);
function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
interface classInterface {
newProperty: string;
hello: string;
}
//trick
interface Greeter extends classInterface { };
@classDecorator
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
const b = new Greeter();
console.log(b.newProperty);
看来我们可以使用接口技巧来解决问题。 技巧参考: https ://stackoverflow.com/a/52373394/4831179
我能找到的最佳解决方案是:
export function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
class Greeter {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
注意:这不是最优的,因为它使Greeter.name
返回一个空字符串! 该线程中的其他答案也是如此,所以我仍在寻找解决方案。
不是直接的解决方案,而是避免装饰器限制的解决方法:在某些情况下,可以将装饰器替换为可以正确继承类型的普通类。
class ClassDecorator {
newProperty = "new property";
hello = "override";
}
class Greeter extends ClassDecorator {
property = "property";
hello: string;
constructor(m: string) {
this.hello = m;
}
}
console.log(new Greeter("world"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.