
紅燈停、綠燈行,那黃燈呢?
就讓Type Guard(型別檢測)告訴你吧~
─────────────────────────── By Opshell
Type Guard(型別檢測)在JavaScript中其實也是有型別的,
只是他很善變,在不知道發生什麼事的情況下,
很容易就臉盲了,套一句某客戶對我說的話:
你這樣很不穩定ㄟ(吐血)
Type Guard(型別檢測)
他的工作是在執行時,Narrowing(限縮型別)的表達式,
是使用各種方式判斷、轉換型別,來導流處理,
避免TS在compile(編譯)時報錯。
下面是常見的幾種方式:
- 使用 JS 運算子:
 typeof、instanceof或isArray等- 使用使用者自定義的型別檢查:
 型別謂語(type predicates)、in 關鍵字
typeof用來檢測未經計算的資料型別。
※ 在使用typeof運算子時,有幾個型別要特別小心,
分別是原始型別的null以及Array,兩者判斷後的結果都是物件。
 // 讓我們利用"型別檢測"來修改之前的 getAgeLength function
 // 之前利用(<string>.age)的方式來處理,
 // 現在改成透過型別檢測判斷是否為字串,進行導流
 // 在某方面來說,可讀性更好。
 function getAgeLength(age: string | number): number {
     let result = 0;
     if (typeof age === 'string') {
         result = age.length;
     } else {
         result = age.toString().length;
     }
     return result;
 }
instanceof是用來判斷A是否為B的實例,比較的是原型(prototype)
換句話說,就是有沒有在原型鏈上面
 // 建立Member Class 設定 名稱、年紀、性別為建構子
 class Member {
     constructor(public name: string, public year: number, public gender: string) { }
 }
 // 建立Team Class 團隊名稱、團隊成員 性別為建構子
 // 這邊可以看出 members建構子的型別是 Member Class
 class Team {
     constructor(public title: string, public members: Member[]) { }
 }
 function getName(cls: Member | Team) {
     return (cls instanceof Member) ? cls.name : cls.title;
 }
 const how = new Member('Opshell', 30, 'man');
 const zoo = new Team('Maya', [how]);
 console.log(getName(how)); // Opshell
 console.log(getName(zoo)); // 因為 Team 不在 Member 的原型鏈上面,所以印出 Maya
※
instanceof只能判斷兩個比較對象是否屬於實例關係,無法明確指出具體屬於哪種類型。
ParameterName is Type(型別謂語):是一個具特殊回傳值的函式,
它會向編譯器傳遞訊號,告知回傳值的型別。ParameterName is Type(型別謂語)只能用在單一傳入值,且會回傳布林值。
下面的範例中型別謂語也就是 s is string,語法為參數名 is 型別。
 type tMan = 'xy';
 type tWoman = 'xx';
 function isMan(gender: tMan | tWoman): gender is tMan {
     return (gender as tMan) === 'xy';
 }
 /** 如果gender 沒有使用"斷言"指定型別,
  * 他會被"推論"成字串
  * 這邊就是前面提到的,用"斷言"覆蓋"推論"的做法
  * 無法丟進去isMan做驗證喔
  */
 const Opshell = {
     gender: (<tMan>'xy'),
     year: 30
 };
 console.log(isMan(Opshell.gender)); // true
使用
in 關鍵字會回傳布林值,
判斷屬性是否存在特定物件或其原型鏈上,
語法為 n in x,n 為字串或字串字面值,x 為 union型別
 class Member {
     constructor(public name: string, public year: number, public gender: string) { }
 }
 class Team {
     constructor(public title: string, public members: Member[]) { }
 }
 function isMember(cls: any): cls is Member {
     return 'name' in cls;
 }
 const Opshell = new Member('Opshell', 30, 'man');
 const Zoo = new Team('Maya', [Opshell]);
 console.log(isMember(Opshell)); // true
 console.log(isMember(Zoo)); // false
看完上面的例子可以發現
Type Guard(型別檢測),
跟我們平常在Js中會做的事情差不多,
判斷型別決定要做的事情,
只是TS提供更多樣、嚴謹的方式來幫助 ~~(強迫)~~你做。
讓程式碼更嚴謹易讀,上面只是一些比較常見的方式,
還有更多厲害的看看延伸閱讀其他大大寫的文章,
在後續的學習中,也會看到更多樣的型別檢測(Type Guard)方式,
大家明天見囉~