NG筆記25-如何將Directive Isolated Scope宣告為TypeScript強型別?

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
歡迎推文分享:
Published 25 March 2015 11:34 PM 由 Jeffrey
Filed under: ,
Views: 3,881



意見

# ChrisTorng said on 25 March, 2015 09:28 PM

github.com/.../angularjs 中其實都有 interface ICustomScope extends ng.IScope 的範例說明,我很早就這麼用的了。

以您的 directives 寫法,其實還不太 TypeScript/Definitely 化...

比如,在 github.com/.../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;

 }

}

# Jeffrey said on 26 March, 2015 12:44 AM

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

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<March 2015>
SunMonTueWedThuFriSat
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication