具有所需方法的类装饰器签名

时间:2017-04-17 02:30:11

标签: javascript typescript ecmascript-6

我想在typescript中为已经存在的javascript代码定义类装饰器的装饰器签名。假设我已经定义了一些类Foo

class Foo {
  someMethod() {
  }
}

然后还有一些类装饰器方法,它接受输入类,但它要求输入类在装饰之前定义了一些其他方法。

function decorate(someClass) {
  // some properties and methods injection happens here
}

然后在我的打字稿代码中,我将创建一个类来装饰:

class Bar extends Foo {
  requiredMethod(): any {
    return null;
  }
}

然后我尝试了定义:

interface WithRequiredMethod {
  requiredMethod(): any;
}

declare function decorate<C extends Foo>(input: C & WithRequiredMethod): C;

然后将其称为:

const DocoratedBar = decorate(Bar);

不幸的是,即使已定义requiredMethod,打字稿也无法将Bar识别为有效输入。有没有办法定义decorate签名来验证输入类上requiredMethod的存在?

1 个答案:

答案 0 :(得分:0)

你几乎拥有它。但你需要写这个

interface WithRequiredMethod {
  // tslint:disable-next-line:no-any
  requiredMethod(): any;
}

declare function decorate<C extends new () => Foo & WithRequiredMethod>(target: C): C;

原因是装饰者以一个类为目标。一个类实际上只是一个构造函数。因此,被装饰的对象实际上是Foo & WithRequiredMethod类型的对象的构造函数。

例如,如果我们只想将装饰器限制为定位Foo或其中一个子类,我们就会编写

declare function decorate<T extends typeof Foo>(target: T): T;

有趣的是,最初收到的错误表明class Bar没有实现WithRequiredMethod,这确实是正确的,但不是我们想说的。但是,它可能很有用,我们可以利用装饰器强制执行静态和实例属性。

考虑:

declare function decorate<
  C extends WithRequiredMethod & (new () => Foo & WithRequiredMethod)
>(target: C): C;

现在我们将其应用于class Bar并再次收到requiredMethod丢失的错误。但是,我们可以通过向requiredMethod添加静态Bar方法来满足要求:

@decorate class Bar extends Foo {
  // required by `decorate`
  static requiredMethod() {
    // tslint:disable-next-line:no-null-keyword
    return null;
  }

  // also required by `decorate`
  requiredMethod() {
    // tslint:disable-next-line:no-null-keyword
    return null;
  }
}