NG範例23-使用Directive建立自訂網頁元素介紹過好用的自訂元素。除了資料互動不高的單純DOM操作Directive,一般我們都會另建獨立Scope(Isolated Scope)避免彼此干擾。而Isolated Scope宣告時需指定{ propA: "=", propB: "@" }形式的scope物件,供NG參照建立參數對應,因此不像Controller、Service可以寫成獨立類別,而這衍生的副作用則是-scope參數在link函式裡被視為任意型別(any),難以享受TypeScript的強型別優勢。

舉個例子,以下模擬一個整合KendoGrid建立的Directive,其中宣告獨立Scope,對應到data、timestamp、columns、editable四個聯外參數,而在link函式中還在scope增加了options屬性,方便後續繫結到k-options。遇到這種狀況,我們直覺上會將scope宣告為any型別,否則TypeScript會抱怨scope不支援data、colums等屬性。但怎麼一來,scope與scope的屬性也都變成any型別,Visual Studio甚至連scope.$watch也認不出來,強型別優勢盡失。

幾經嘗試,我找到一個不錯的解決方案。

做法是多宣告一個ICustScope,依一般interface的做法宣告scope會用到的屬性或方法名稱及其型別,並記得extends ng.IScope。接著在link函式中,我們將scope宣告為ICustScope型別,讓scope成為不折不扣的強型別變數,後續開發才能保有Intellisense的便利及型別檢查的保護,充分享受使用TypeScript的優勢。同時,因為ICustScope繼承了ng.IScope,link函式裡的scope.$watch也能被正確識別。

由於ICustScope為此Directive專屬,不需export到module之外,可設為私有interface,有效範圍只在此段module directives的 「{」與「}」之間,而且interface只存在TypeScript世界,不實際產生JavaScript程式,故每個Directive用的Scope定義都取名ICustScope也不是問題,不需要擔心各Directive的自訂Scope介面名稱相衝。

註:舊版TypeScript不允許在對外函式link函式的參數型別使用私有Interface ICustScope,升級TypeScript 1.4後已無此限制。

題外話:TypeScript已經成為Angular 2.0的奧林匹克指定開發語言,又多了一項強而有力的學習理由!以我自己為例,在習慣TypeScript強型別的好處後,開始覺得過去一天到晚因打錯字被JavaScript陰,函式變數名稱沒取好也沒勇氣改的日子,真不是人過的…(謎之聲:接手維護你那些JavaScript的日子才不是人過的吧!)

【延伸閱讀】

 

[NG系列]

http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs

Comments

# by ChrisTorng

在 https://github.com/borisyankov/DefinitelyTyped/tree/master/angularjs 中其實都有 interface ICustomScope extends ng.IScope 的範例說明,我很早就這麼用的了。 以您的 directives 寫法,其實還不太 TypeScript/Definitely 化... 比如,在 https://github.com/borisyankov/DefinitelyTyped/blob/master/angularjs/angular.d.ts 中有 interface IDirective 可用,也可以跟著查到 interface IDirectiveLinkFn 的完整變數宣告型別。 依您範例,我會將 simpleGrid 段落這麼寫 (純手工寫,沒有編譯,很可能會有錯): export class simpleGrid { constructor() { var directive: ng.IDirective = {}; directive.scope = { ... }; directive.link = function(scope: ICustScope, element: ng.IAugmentedJQuery, attr: ng.IAttributes):void { ... }; return directive; } }

# by Jeffrey

to ChrisTorng,謝謝你的分享與補充!

Post a comment