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