我想在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
的存在?
答案 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;
}
}