TypeScript中的聯(lián)合類型使用示例詳解
一. TS類型系統(tǒng)有哪些運算
聯(lián)合類型,以下是具體的例子,理解成集合的并集
type?A1?=?number;
type?B1?=?string;
type?C1?=?A1?|?B1;
const?c1:?C1?=?42;
//?這種可以理解成集合的并集,但是他們沒有交集
type?A2?=?{?name:?string?};
//?這里要理解成?A2表示name為string的所有對象,比如{name:?'a',?age:?14},?它既可以有age也可以沒age
type?B2?=?{?age:?number?};
type?C2?=?A2?|?B2;
const?c2:?C2?=?{
??name:?'John',
??age:?18,
};
//?這種可以理解成兩個集合的并集,并且他們有交集二. 如何使用聯(lián)合類型?
用的時候必須拆開,不然只能用number和string同時擁有的方法或者屬性
這種縮小類型范圍的過程我們叫做類型收窄(narrowing)
const?f1?=?(a:?number?|?string)?=>?{
??if?(typeof?a?===?'number')?{
????a.toFixed();
??}?else?{
????a.split(',');
??}
};三. typeof的局限性
typeof 作用于數(shù)組對象,普通對象,日期對象,null都是返回object
四. 使用instanceof來區(qū)分類型
const?f1?=?(a:?Date?|?Date[])?=>?{
??if?(a?instanceof?Date)?{
????a;
??}?else?{
????a;
??}
};五. instanceof的缺點
不支持string,number,boolean等基本類型
我們可以將instanceof 和 typeof結合解決這個問題
const?f1?=?(a:?Date?|?string?|?Date[])?=>?{
??if?(typeof?a?===?'string')?{
????a;
??}?else?if?(a?instanceof?Date)?{
????a;
??}?else?{
????a;
??}
};不支持TS獨有的類型,也就是那些會被擦除的類型
用in解決,但是這個方案也只能解決部分問題,比如無法區(qū)分兩個函數(shù)
type?Person?=?{
??name:?string;
};
type?Animal?=?{
??x:?string;
};
const?f1?=?(a:?Person?|?Animal)?=>?{
??if('name'?in?a)?{
????a
??}?else?if?('x'?in?a)?{
????a
??}?else?{
????a
??}
}ts官方文檔上也介紹了一些收窄類型的方案
六. ts中的區(qū)分類型方法
以上所講都是根據(jù)js中的方式來區(qū)分類型,接下來我們討論下ts中的類型區(qū)分方法
類型謂詞/類型判斷 is, is的優(yōu)點支持所有ts類型,is的缺點麻煩。
type?Rect?=?{
??height:?number;
??width:?number;
};
type?Circle?=?{
??center:?[number,?number];
??radius:?number;
};
const?f1?=?(a:?Rect?|?Circle)?=>?{
??if?(isRect(a))?{
????a;
??}
};
//?這里x?is?Rect就是類型謂詞,用于收窄類型,寫boolean不行,因為這里寫boolean的話ts不知道boolean的含義是什么
function?isRect(x:?Rect?|?Circle):?x?is?Rect?{
??return?'height'?in?x?&&?'width'?in?x;
}使用可辨別聯(lián)合類型,加字段來表示,好處讓復雜類型的收窄變成簡單類型的對比
- 可以使用這種方式的條件 T = A | B | C | D ...
A,B,C,D...有相同屬性kind或其它
kind的類型是簡單類型
各類型中的kind可區(qū)分
總結: 我們需要一個同名,可辨別的簡單類型的key,這樣的T類型我們稱為可辨別聯(lián)合類型
type?Circle?=?{?kind:?'Circle';?center:?[number,?number]?};
type?Square?=?{?kind:?'Square';?sideLength:?number?};
//?兩個聯(lián)合起來的類型通過加上kind字段來進行判斷類型
type?Shape?=?Circle?|?Square;
const?f1?=?(a:?string?|?number?|?Shape)?=>?{
??if?(typeof?a?===?'string')?{
????a;
??}?else?if?(typeof?a?===?'number')?{
????a;
??}?else?if?(a.kind?===?'Circle')?{
????a;
??}?else?{
????a;
??}
};補充一個使用可辨別聯(lián)合類型的場景
在react中我們會經常這樣寫,比如對一個用戶增刪改查
type?Action?=
??|?{?type:?'getUser';?id:?string?}
??|?{?type:?'createUser';?attributes:?any?}
??|?{?type:?'deleteUser';?id:?string?}
??|?{?type:?'updateUser';?attributes:?any?};
使用斷言
type?Circle?=?{?kind:?'Circle';?center:?[number,?number]?};
type?Square?=?{?kind:?'Square';?x:?number?};
type?Shape?=?Circle?|?Square;
const?f1?=?(a:?Shape)?=>?{
??(a?as?Circle).center;?//?這就是斷言
};
f1({?kind:?'Circle',?center:?[1,?2]?});七. any是否是所有類型(除了never/unknown/any/void)的聯(lián)合?為什么?
不是,因為一旦兩個類型聯(lián)合起來,只能用此兩個類型共有的方法,而any可以使用所有類型的方法
const?f1?=?(a:?number?|?string)?=>?{
??a.toFixed();?//?會報錯
??a.split();?//?會報錯
??a.toString();?//?只能用number和string共有的方法
};
const?f2?=?(a:?any)?=>?{
??a.toFixed();?//?不會報錯
??a.split();?//?不會報錯
};any有點像法外狂徒,ts絕大部分規(guī)則對any不生效
const?f1?=?(a:?any)?=>?{
??const?b:?never?=?a;?//?會報錯,這算是any唯一不能違反的規(guī)則
};那么什么是所有類型(除了never/unknown/any/void)的聯(lián)合
unknown,因為unknown可以收窄到任何類型,也就是說它是任何類型的聯(lián)合
const?f1?=?(a:?unknown)?=>?{
?if(a?instanceof?Date)?{
???a?//?Date
?}
?if(isPerson(a))?{
???a?//?Person
?}
}以上就是TypeScript中的聯(lián)合類型使用示例詳解的詳細內容,更多關于TypeScript聯(lián)合類型的資料請關注腳本之家其它相關文章!
相關文章
TypeScript實現(xiàn)類型安全的EventEmitter
這篇文章主要為大家介紹了TypeScript實現(xiàn)類型安全的EventEmitter示例詳解有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
Typescript是必須要學習嗎?如何學習TS全棧開發(fā)
Typescript目前在前端,網站,小程序中的位置基本無可替代,同時也可以構建完美的CLI應用。在移動,桌面,后端方面,性能不是要求很高的情況下完全可以勝任,并且在區(qū)塊鏈,嵌入式,人工智能方面也開始茁壯成長。2022-12-12
layui.layer彈出層(子頁面)改變父頁面內容(訪問元素和函數(shù))
當前頁面(父框架或父頁面)使用layer以iframe層的方式彈出新的窗口(子框架或子頁面)時,如何在子頁面中訪問父頁面的元素和函數(shù),從而改變父元素的頁面顯示,給用戶合理舒適的體驗。2023-02-02
Webpack source map實戰(zhàn)分析詳解
這篇文章主要為大家介紹了Webpack source map示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12

