紅燈停、綠燈行,那黃燈呢?
就讓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)
方式,
大家明天見囉~