首页 文章

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

提问于
浏览
2

假设我有一个装饰器,如下面的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 回答

  • 1

    设计的装饰者不允许改变他们装饰的类型的结构 . 支持这种方法的方法是使用mixin,如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"
    

相关问题