我最近在我的打字稿项目中更新了我的angular.d.ts文件。我现在在指令定义中得到一个打字稿编译错误。我在更新的angular.d.ts文件中注意到以下内容:
interface IDirectiveFactory {
(...args: any[]): IDirective;
}
我想弄清楚如何实现这个界面。
我收到此编译错误:输入ng.DirectiveFactory需要调用签名,但键入" MyDirective"缺乏。
这是我的指令现在看起来的样子(以前用于较旧的angular.d.ts文件可以正常工作):
class MyDirective{
constructor() {
var directive: ng.IDirective = <ng.IDirective>{};
directive.priority = 0;
directive.restrict = "E";
directive.scope = {...};
directive.template = '<div></div>';
directive.link = {...}
return directive;
}
}
这是我用angular:
注册MyDirective类的地方angular.module("MyModule", [])
.directive('myDirective', MyDirective);
上面的编译错误很有道理,但我如何实现(... args:any []):IDirective签名??
提前致谢
答案 0 :(得分:12)
我知道这是一个老问题,但我也遇到了这个问题,并且认为我会分享我的解决方案:
class MyDirective implements ng.IDirective {
priority = 0;
restrict = 'E';
scope = {...};
template = '<div></div>';
link(scope: ng.IScope
, element: ng.IAugmentedJQuery
, attributes: IAttributes
, controller: any
, transclude: ng.ITranscludeFunction) {
...
}
}
angular.module("MyModule", [])
.directive('myDirective', () => new MyDirective());
我喜欢这个解决方案,因为它允许您使用TypeScript类的全部好处。
<强>更新强> 如果您想使用此方法来使用私有类函数或字段来简化链接函数,则需要稍微不同地定义链接函数:
class MyDirective implements ng.IDirective {
priority = 0;
restrict = 'E';
scope = {...};
template = '<div></div>';
link = (scope: ng.IScope
, element: ng.IAugmentedJQuery
, attributes: IAttributes
, controller: any
, transclude: ng.ITranscludeFunction) => {
...
}
}
angular.module("MyModule", [])
.directive('myDirective', () => new MyDirective());
(请注意,此处将链接方法声明为胖箭头函数而不是类函数)
这是因为当Angular将其连接起来时,它会以不保留类的this
引用的方式进行连接。通过使用胖箭头函数定义它,编译的JavaScript将以保留this
引用的方式定义函数。否则,在尝试运行代码时会出现很多错误。
答案 1 :(得分:9)
directive()
的旧签名曾经是......
directive(name: string, directiveFactory: Function): IModule;
将一个类用作Function
是合法的。但是this commit将签名更改为:
directive(name: string, directiveFactory: IDirectiveFactory): IModule;
IDirectiveFactory
是一个返回IDirective
的函数,因此directive()
不再接受directiveFactory
参数的类。将其更改为...
function MyDirective () : ng.IDirective {
var directive: ng.IDirective = <ng.IDirective>{};
directive.priority = 0;
directive.restrict = "E";
directive.scope = {};
directive.template = '<div></div>';
return directive;
}
angular.module("MyModule", [])
.directive('myDirective', MyDirective);
答案 2 :(得分:2)
Joe Skeen提供了一个完全符合我要求的答案。
还有另外一个人Aaron Holmes为他制定了类似的解决方案,其中包括对处理链接的一些改进。
http://blog.aaronholmes.net/writing-angularjs-directives-as-typescript-classes/#comment-2111298002
与Joe的上述答案相反,不是直接引用ng.IScope,而是使用接口,您可以用TypeScript方式定义自己的范围变量(intellisense!)
将链接逻辑移动到构造函数似乎是一种更好的方法。
link = (scope: ng.IScope
, element: ng.IAugmentedJQuery
, attributes: IAttributes
, controller: any
, transclude: ng.ITranscludeFunction) => {
...
}
为:
link = (scope: IMyScope
, element: ng.IAugmentedJQuery
, attributes: IAttributes
, controller: any
, transclude: ng.ITranscludeFunction) => {
...
}
以下是Aaron的完整示例:
module MyModule.Directives
{
export interface IMyScope: ng.IScope
{
name: string;
}
export class MyDirective
{
public link: (scope: IMyScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes) => void;
public template = '<div>{{name}}</div>';
public scope = {};
constructor()
{
MyDirective.prototype.link = (scope: IMyScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes) =>
{
scope.name = 'Aaron';
};
}
public static Factory()
{
var directive = () =>
{
return new MyDirective();
};
directive['$inject'] = [''];
return directive;
}
}
}
一个陷阱:你需要使用冒号&#34;:&#34;而不是&#34; =&#34;如果您将链接逻辑移动到构造函数中,则在声明链接时。