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系列]