假设我有一个如下的装饰器
example
会添加带有预设值的新name
属性。
有没有办法告诉Typescript我的装饰器添加了此属性,以便所有装饰的类都能正确键入?
示例代码:
function withName(name) {
return (target) => {
target.prototype.name = name;
}
}
@withName('Karl')
class Person {
greet() {
console.log("Hi I'm ", this.name);
}
}
const karl = new Person();
karl.greet(); // Will log: "Hi I'm Karl"
console.log(karl.name); // <- Will cause a TypeScript error: "Property 'name' does not exist on type 'Person'"
答案 0 :(得分:2)
不允许装饰设计者更改其装饰类型的结构。一种支持的方式是使用混合,如here
所述function withName(nameValue: string) {
return <T extends new (...args: any[]) => any>(target: T) => {
return class extends target {
name: string = nameValue
}
}
}
const Person = withName("Karl")(class {
greet() {
console.log("Hi I'm ...");
}
});
const karl = new Person();
console.log(karl.name);
上面的方法仅将类扩展到外部世界,因此从类内部看不到添加的成员。我们可以扩展Person
的基类(如果没有基类,则使用空类)来访问扩展类内部添加的字段:
class Person extends withName("Karl")(class { }) {
greet() {
console.log("Hi I'm ", this.name);
}
}
const karl = new Person();
karl.greet(); // Will log: "Hi I'm Karl"