是否可以键入由装饰器添加的属性?

时间:2018-06-20 08:10:19

标签: javascript typescript

假设我有一个如下的装饰器 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'"

1 个答案:

答案 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"
相关问题