假设我有一个指令装饰器,它向其名为factory的目标添加一个静态方法:
function Directive<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
static factory(...args): ng.IDirectiveFactory {
const c: any = () => {
return constructor.apply(this, args);
};
c.prototype = constructor.prototype;
return new c(...args);
}
};
}
我还通过界面添加类型:
interface BaseDirective extends ng.IDirective {
factory(): ng.IDirectiveFactory;
}
为什么我的班级声明:
@Directive
class FocusedDirective implements BaseDirective {....
我得到Class 'FocusedDirective' incorrectly implements interface 'BaseDirective'.
Property 'factory' is missing in type 'FocusedDirective'.
我错误地期望@Directive
为我添加这个遗失的财产?
答案 0 :(得分:2)
装饰者不能改变类的类型,你可以将你的装饰器作为一个函数调用并存储将包含该方法的新类,并使用新类而不是原来的类:
const FocusedDirectiveWithDirective = Directive(FocusedDirective);
您可以使用类表达式完全取消中间类:
const FocusedDirective = Directive(class implements BaseDirective{
});
答案 1 :(得分:1)
你有两个问题。第一个与装饰器几乎没有关系:factory
是实现中的静态方法,但在接口中是常规方法:
interface BaseDirective {
factory(): ng.IDirectiveFactory;
}
这对你来说是个问题。现在我要将实现转换为常规方法,因为它更容易实现。
function Directive<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
factory(...args: any[]): ng.IDirectiveFactory {
const c: any = () => {
return constructor.apply(this, args);
};
c.prototype = constructor.prototype;
return new c(...args);
}
};
}
第二个问题:装饰者不会以你期望的方式改变类签名。这是一个oft-requested feature,并且有一些有趣的问题,为什么它不是一个简单的问题需要解决。重要的是,要弄清楚如何支持让类的实现引用变异类型并不容易。在您的情况下:{....
内的内容是否会知道factory()
?大多数人似乎都会期待它,但尚未应用装饰器。
解决方法是根本不使用装饰器语法,而是使用装饰器函数作为常规函数来创建新类。语法如下所示:
class FocusedDirective extends Directive(class {
// any impl that doesn't rely on factory
prop: string = "hey";
foo() {
this.prop; // okay
// this.factory(); // not okay
}
}) implements BaseDirective {
// any impl that relies on factory
bar() {
this.prop; // okay
this.foo(); // okay
this.factory(); // okay
}
}
这也解决了“实现了解装饰器”的问题,因为装饰器功能中的东西没有,而外面的东西也是如此,如上所示。
回到静态/实例问题。如果要在类的静态方面强制实施约束,则不能通过让类实现任何内容来实现。相反,您需要在类构造函数本身上强制执行静态方面。像这样:
interface BaseDirective {
// any actual instance stuff here
}
interface BaseDirectiveConstructor {
new(...args: any[]): BaseDirective;
factory(): ng.IDirectiveFactory;
}
class FocusedDirective extends Directive(class {
// impl without BaseDirectiveConstructor
}) implements BaseDirective {
// impl with BaseDirectiveConstructor
bar() {
FocusedDirective.factory(); // okay
}
}
function ensureBaseDirectiveConstructor<T extends BaseDirectiveConstructor>(t: T): void {}
ensureBaseDirectiveConstructor(FocusedDirective);
ensureBaseDirectiveConstructor()
函数确保FocusedDirective
类构造函数具有正确类型的静态factory()
方法。如果你没有实现静态方面,那就是你会看到错误的地方。
好的,希望有所帮助。祝你好运。