TypeScript 型別保護
在TypeScript 聯合型別一章節介紹過,如果一個值是聯合型別,那麼只能訪問聯合型別的共有成員。
程式碼例項如下:
[typescript] 純文字檢視 複製程式碼class Bird{ leg=2; color="white"; fly(){ // code } } class Insect { leg=8; color="black"; eat(){ // code } } function antzone(): Bird | Insect { return new Bird(); } let ant = antzone(); ant.color; ant.leg; ant.eat()// 報錯,只能訪問共有成員
antzone()函式返回值是聯合型別,也就是既有可能是Bird型別,也有可能是Insect型別。
有時候我們想確切的知道這個返回值到底是屬於哪個型別,在原生JavaScript中,判斷這個非常簡單。
只要判斷物件是否具有對應屬性即可,但是在TypeScript可能並不適用,看如下程式碼例項:
[JavaScript] 純文字檢視 複製程式碼let ant= antzone(); if(ant.fly){ ant.fly(); }else if(ant.eat){ ant.fly(); }
上面的程式碼會報錯,因為只能訪問聯合型別的共有成員;程式碼修改如下:
[typescript] 純文字檢視 複製程式碼let ant= antzone(); if((<Bird>ant).fly){ (<Bird>ant).fly(); }else if((<Insect>ant).eat){ (<Insect>ant).eat(); }
雖然使用斷言解決此問題,但比較繁瑣,if語句中使用了斷言,語句塊中還是要斷言。
較好的解決方案是,只要判斷成功,後面對應作用域中的型別就確定。
TypeScript型別保護機制提供了這樣的功能,下面分別做一下介紹。
一.自定義的型別保護:
型別保護是一些表示式,它們會檢查以確保在某域裡的型別。
要定義一個型別保護,只要定義一個函式,它的返回值是一個型別謂詞。
程式碼例項如下:
[typescript] 純文字檢視 複製程式碼function isBird(ant: Bird | Insect): ant is Bird { return (<Bird>ant).fly !== undefined; }
"ant is Bird"是一個型別謂詞,格式如下:
[typescript] 純文字檢視 複製程式碼parameterName is Type
parameterName必須是當前函式簽名裡的一個引數名。
如果函式返回值為true,那麼也就意味著型別謂詞是成立的,於是它後面作用域的型別也就被固定為Type。
程式碼例項如下:
[typescript] 純文字檢視 複製程式碼let ant=antzone(); function isBird(ant: Bird | Insect): ant is Bird { return (<Bird>ant).fly !== undefined; } if (isBird(ant)) { ant.fly(); } else { ant.eat(); }
只要isBird(ant)成立,那麼它後面作用域中的型別就確定為Bird。
二.typeof型別保護:
在TypeScript中,typeof在判斷資料型別的同時,直接提供了型別保護功能。
程式碼例項如下:
[typescript] 純文字檢視 複製程式碼function ant(param: string | number) { if (typeof param === "number") { console.log(param+5); } if (typeof param === "string") { console.log(param+"螞蟻部落"); } }
typeof實現了型別保護及功能,截圖如下:
原本是聯合型別,由於應用了typeof,後面作用域的param就確定為number型別。
typeof型別保護只有兩種形式能被識別:typeof v === "typename"和typeof v !== "typename"。
"typename"必須是"number","string","boolean"或"symbol"。
但是TypeScript並不會阻止與其它字串比較,語言不會把那些表示式識別為型別保護。
三.instanceof型別保護:
instanceof的使用方式和typeof非常的類似,程式碼例項如下:
[typescript] 純文字檢視 複製程式碼interface Padder { getPaddingString(): string } class SpaceRepeatingPadder implements Padder { constructor(private numSpaces: number) { } getPaddingString() { return Array(this.numSpaces + 1).join(" "); } } class StringPadder implements Padder { constructor(private value: string) { } getPaddingString() { return this.value; } } function getRandomPadder() { return Math.random() < 0.5 ? new SpaceRepeatingPadder(4) : new StringPadder(" "); } // 型別為SpaceRepeatingPadder | StringPadder let padder: Padder = getRandomPadder(); if (padder instanceof SpaceRepeatingPadder) { padder; // 型別細化為'SpaceRepeatingPadder' } if (padder instanceof StringPadder) { padder; // 型別細化為'StringPadder' }
四.switch case型別保護:
通過switch case來實現型別保護,原理都是一樣的。
程式碼例項如下:
[typescript] 純文字檢視 複製程式碼interface Square { kind: "square"; size: number; } interface Rectangle { kind: "rectangle"; width: number; height: number; } interface Circle { kind: "circle"; radius: number; } type Shape = Square | Rectangle | Circle; function area(shape: Shape) { switch (shape.kind) { case "square": return shape.size * shape.size; case "rectangle": return shape.height * shape.width; case "circle": return Math.PI * shape.radius ** 2; } }
特別說明:型別保護並不僅限於以上幾種,大致能夠實現型別識別,即可實現型別保護。
相關文章
- 聊聊 TypeScript 中的型別保護TypeScript型別
- 5種在TypeScript中使用的型別保護TypeScript型別
- Typescript 下 Mongoose 外來鍵型別&外來鍵陣列型別定義&型別保護&聯合型別理解TypeScriptGo型別陣列
- TypeScript this型別TypeScript型別
- TypeScript 泛型型別TypeScript泛型型別
- Typescript:基本型別TypeScript型別
- TypeScript Widened型別TypeScriptIDE型別
- TypeScript Never型別TypeScript型別
- TypeScript Any型別TypeScript型別
- TypeScript 索引型別TypeScript索引型別
- TypeScript 型別相容TypeScript型別
- TypeScript 交叉型別TypeScript型別
- TypeScript void 型別TypeScript型別
- TypeScript 字串型別TypeScript字串型別
- TypeScript 型別安全TypeScript型別
- TypeScript type 型別別名TypeScript型別
- TypeScript 聯合型別TypeScript型別
- TypeScript 數值型別TypeScript型別
- TypeScript 布林型別TypeScript型別
- Typescript高階型別TypeScript型別
- TypeScript 對映型別TypeScript型別
- TypeScript 函式型別TypeScript函式型別
- TypeScript資料型別TypeScript資料型別
- TypeScript 型別系統TypeScript型別
- TypeScript 型別推斷TypeScript型別
- TypeScript 型別斷言TypeScript型別
- TypeScript 陣列型別TypeScript陣列型別
- TypeScript 字面量型別TypeScript型別
- c++語言中類的私有型別或保護型別成員變數C++型別變數
- TypeScript型別系統和基礎型別TypeScript型別
- typeScript 型別斷言、聯合型別和交叉型別(七)TypeScript型別
- TypeScript 混合型別介面TypeScript型別
- TypeScript Null和Undefined 型別TypeScriptNullUndefined型別
- TypeScript-----資料型別TypeScript資料型別
- TypeScript 字串字面量型別TypeScript字串型別
- 【譯】TypeScript 的型別(一)TypeScript型別
- typeScript 基礎型別 (三)TypeScript型別
- TypeScript 之對映型別TypeScript型別