Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript:一个类方法可以是另一个方法的装饰器吗?_Typescript - Fatal编程技术网

Typescript:一个类方法可以是另一个方法的装饰器吗?

Typescript:一个类方法可以是另一个方法的装饰器吗?,typescript,Typescript,你能做一些像下面这样的工作吗 class A { private mySecretNumber = 2; decorate (f: (x :number) => number) { return (x: number) => f(this.mySecretNumber * x); } @(this.decorate) method (x: number) { return x + 1; } } 我尝试了@this['decoration'

你能做一些像下面这样的工作吗

class A {
  private mySecretNumber = 2;

  decorate (f: (x :number) => number) {
    return (x: number) => f(this.mySecretNumber * x);
  }

  @(this.decorate)
  method (x: number) {
    return x + 1;
  }
}
我尝试了
@this['decoration'],
@A['decoration']
@A.decoration
,但什么也找不到


下面是我的用例示例:。理想情况下,我只需要修饰一下
getAbc()
get123()

你的问题有很多微妙之处

第一件事是,是的,你确实可以使用一个方法作为装饰器,但不是通过编写
@this.decoration
(在传输过程中,
这个
将是
全局,而不是
a
)或
@a.decoration
装饰
不是一个静态方法,因此
a.decoration
不存在)。这部分问题的正确答案是
@A.prototype.decoration
;这将准确定位您的想法

第二件事是,当对类的方法应用decorator时,decorator的参数不是方法函数本身,而是它实际上有3个参数:一个目标对象(在本例中是
a.prototype
),一个字符串(方法的名称,在本例中是
“method”
),和属性描述符对象。它也不会返回一个新函数,但如果不是void,它应该返回一个新的属性描述符。因此,在decorator函数中,您应该尝试修改目标对象,而不是尝试返回新函数

综合起来,一个有效的例子是:

class A {
    private mySecretNumber = 2;

    decorate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        var f = descriptor.value;
        // Don't use arrow function here, otherwise "this"
        // will not be the current A instance.
        descriptor.value = function(x: number) {
            return f(this.mySecretNumber * x);
        };
        Object.defineProperty(target, propertyKey, descriptor);
    }

    @A.prototype.decorate
    method(x: number) {
        return x + 1;
    }
}

var a = new A();
console.log(a.method(3)); // 7
更新: 基于您的用例,我将使用以下方法。基本上,您可以使用静态装饰器来加载抽象的
decoration
方法,该方法可以在子类中实现。我对上面的例子进行了修改,让您了解如何做到这一点

abstract class A {
    protected abstract decorate(x: number): number;

    static decorate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        var f = descriptor.value;
        descriptor.value = function(x: number) {
            return f(this.decorate(x));
        };
        Object.defineProperty(target, propertyKey, descriptor);
    }

    @A.decorate
    method(x: number) {
        return x + 1;
    }
}

class B extends A {
    private mySecretNumber = 2;
    protected decorate(x: number) { return this.mySecretNumber * x; }
}

var b = new B();
console.log(b.method(3)); // 7

您可以通过使用类型约束实现装饰器来实现这一点,该类型约束将装饰器的适用性限制在实现
mySecretNumber
属性的类上。这将修复Mu Tsun Tsai提出的范围界定问题的语法和语义

以下是我想要的:

class A {
    mySecretNumber = 2;
    @decorate
    method(x: number) {
        return x + 1;
    }
}

function decorate<T extends { mySecretNumber: number }, K extends keyof T>(
    target: T, key: K,
    descriptor: T[K] extends (n: number) => number ? TypedPropertyDescriptor<(n: number) => number> : never
) {
    const f = descriptor.value;
    if (f) {
        descriptor.value = function (this: T, x: number) {
            return f(this.mySecretNumber * x);
        };
    }
    return descriptor;
}
A类{
mySecretNumber=2;
@装饰
方法(x:编号){
返回x+1;
}
}
功能装饰(
目标:T,键:K,
描述符:T[K]扩展(n:number)=>number?类型属性描述符number>:从不
) {
常数f=描述符值;
如果(f){
descriptor.value=function(this:T,x:number){
返回f(this.mySecretNumber*x);
};
}
返回描述符;
}

这可以确保修饰类具有类型为
number
mySecretNumber
属性,将该成员绑定到所需的
This
,并且作为奖励,可以确保修饰方法具有正确的签名。

我删除了我的答案,因为创建该类的实例对您有利(我建议的方法)表示decorator将有权访问
这个
实例,但事实证明它没有。对于“方法decorator”来说,这似乎是最好的选择它是静态的,因为它将无法访问
this
。是的,我自己也会使用静态装饰器。老实说,非静态装饰器通常没有什么意义,但弄清楚它是否可以完成仍然很有趣。我的用例是我有一个抽象类,其中
装饰()
是抽象的,
method()
的定义如示例中所示。在我的具体类中,我只需要实现
decoration()
。但是在TS中你不能有抽象的静态方法,有没有其他“更干净”的方法来实现这一点的想法?好的,那么在你的抽象类中有一个具体的
方法()
,您想在子类中对其进行修饰,对每个子类采用不同的方式?我认为您描述的结构无法达到您想要的效果,因为这种修饰不会简单地通过实现
修饰()自动应用于子类
method;您仍然需要在子类中写下
method()
上方的修饰,这样您就不会真正使用任何代码,因此在抽象类中也不需要
decoration()
。我相信您根本不需要使用修饰,您应该重写
method()子类中的
(需要时在新函数中调用
super.method()
)。您能更具体地解释一下您的用例吗?看起来您试图通过在类中定义decorator来保留封装,但实际上,您的私有成员不是私有的,并且有更简单的解决方案允许它是私有的private@AluanHaddad不过,使用通用装饰器有一个缺点:TypeSc在你的例子中,如果你设置
method()
若要保护,则会发生错误。@Mu TsunTsai这是真的,但我不认为这是一个缺点,因为可见性修饰符在TypeScript中是空的,将被提供真正私有成员的未来版本的ECMAScript所取代。如果您想要封装,您需要闭包,而在JavaScript和继续使用TypeScript