带有TypeScript接口的AngularJS指令模型符号

时间:2015-11-23 05:02:51

标签: javascript angularjs typescript

使用强类型接口时,如何初始化AngularJS指令的隔离范围?如果您想使用模型接口以及"@" "=""&"绑定符号,您似乎会混淆编译器,因为您无法将字符串变量分配给不兼容的属性类型。

例如:

module widgets {
    'use strict';

    export interface IWidget extends ng.IScope {
        removed: boolean;
        onChanged: ()=>void;
        description: string;
        toggle:()=>void;
    }

    export class Widget implements ng.IDirective {

        public templateUrl = 'app/widgets/widget.html';
        public restrict = 'E';
        public scope: IWidget = {
            removed: "@",
            onChanged: "&",
            description: "="
        };

        public link: (scope: IWidget, element: ng.IAugmentedJQuery, 
                      attrs: ng.IAttributes) => void;

        static factory(): any {
            /* @ngInject */
            var directive = () => {
                return new Widget();
            };
            return directive;
        }

        constructor() {
            this.link = (scope: IWidget, element: ng.IAugmentedJQuery, 
                         attrs: ng.IAttributes) => {
                var init = () => {
                    scope.toggle = this._toggle.bind(this);
                    scope.$on('$destroy', this.destruct);
                    scope.$apply();
                };
                element.ready(init);
            };
        }

        private _toggle() {
            // updated: this throws the type error
            this.scope.removed = !this.scope.removed;
        }

        private destruct() {    
        }
    }
}

鉴于上述代码,请注意onChanged将产生编译器错误,因为您无法分配字符串“&”一个功能。

您可能会收到以下错误: 2349 Cannot invoke an expression whose type lacks a call signature.

removed属性上的此错误: 2322 Type 'boolean' is not assignable to type 'string'.

实际上,即使您对模型使用any,编译器仍然不会让您在定义属性后更改属性的基础类型。

有什么方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

  

您可能会收到以下错误:2349无法调用类型缺少调用签名的表达式。

主要原因是scope成员需要字符串链接(并且我不再是角度倡导者的原因之一)。

成员onChanged应该可以调用,例如:

    public scope: IWidget = {
        removed: "@",
        onChanged: "&",
        description: "="
    };

    public link: (scope: IWidget, element: ng.IAugmentedJQuery, attrs: ng.IAttributes) => void {
            scope.onChanged(); // WILL WORK FINE
    }

您可能在代码中滥用了注释IWidget(未提供问题)。

答案 1 :(得分:1)

这里的问题是指令定义。

它希望范围有点IDictionary<string, string>,但类型any也可以使用:

export class Widget implements ng.IDirective {

    public templateUrl = 'app/widgets/widget.html';
    public restrict = 'E';
    //public scope: IWidget = {
    public scope: any = {
        removed: "@",
        onChanged: "&",
        description: "="
    };

指令定义中的scope是关于如何处理 html 属性(作为value或{{1}传递) } ...)的类型为function。当范围实例传递到IWidgetIWidget

时,该类型controller将发挥作用

如上所述,link也会起作用:

IDictionary

public scope: {[key: string] : string} = { //public scope: any = { "removed": "@", "onChanged": "&", "description": "=" }; 和简化表示法也会这样做。