亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

TypeScript實用技巧?Nominal?Typing名義類型詳解

 更新時間:2022年09月22日 09:20:32   作者:情緒羊  
這篇文章主要為大家介紹了TypeScript實用技巧?Nominal?Typing名義類型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

Nominal Typing(名義類型)

概念解析

意思是給一個類型附加上一個“名義”,從而防止結構類型在某些情況下由于類型結構相似而被錯用。假設有如下代碼:

interface Vector2D { x: number, y: number };
interface Vector3D { x: number, y: number, z: number };
function calc(vector: Vector2D): void;

const vector: Vector3D = { x: 1, y: 1, z: 1}

calc(vector) // 并沒有拋出錯誤

看上去calc()函數(shù)應該只能傳入Vector2D類型,但其實也可以傳入Vector3D,因為本質上Vector3DVector2D的子集。對于calc()函數(shù)來說,傳入的vector變量的類型中只要同時具有x、y屬性即可通過類型校驗。

這種特性這在TS中被稱為 Structual Typing(結構類型)。通常來說這會給我們的編碼過程帶來便利,但極端情況下,也可能不符合我們的預期。

假如嚴格規(guī)定函數(shù)只能傳入Vector2D類型而不能傳入Vector3D類型,那么在類型實現(xiàn)上,就可以使用 名義上的類型(Nominal Type),通過為原類型添加一個獨有標識來區(qū)分彼此:

interface Vector2D { x: number, y: number, __type: '2d' };
interface Vector3D { x: number, y: number, z: number, __type: '3d' };
function calc(vector: Vector2D): void;

對于interface,我們可以直接為其增加標志屬性,但 primitive types (原始類型) 要如何處理呢?答案是使用交叉類型,例如:

type Food = string & { _type: 'food' };
type Money = number & { _type: 'money' }

你可能會對最終類型有所疑問,但這樣處理之后,他們依舊是原始類型。因為實際上原始類型最終都會解析成對應的 WrapperType (包裹類型),例如string → String,number → Number,就像在JS中一樣。這意味著你可把它們當做原始類型使用:

const money = 100 as Money;
const bill = money * 1; // bill 仍然是 number 類型

雖然這樣的使用方式顯得不太優(yōu)雅,甚至有些繁瑣,但在某些情況下至少可以保證類型安全。假如你的類型系統(tǒng)中有許多 基礎類型單元,那可能會非常有用。

拓展應用

這樣的類型雖然可以被當做原始類型使用,但本質上又不是純粹的原始類型。我們可以利用這個特性,寫出一些非常有趣和實用的類型

例如在字面量枚舉時,我們可以在限制預設值的同時,使用 基于原始類型拓展出來的名義類型 進行兜底,從而使得我們的類型能夠在具備足夠自由性的前提下,仍能享受到TypeScript的類型提示,如下:

可以看到,CustomLiteral名義類型不但可以享受到Literal字面量的類型提示,又能跳出枚舉的限制,使用自定義字符串。倘若我們將Literal和原始類型string直接交叉:

聯(lián)合類型的機制本質上是求并集,而求并集最終得到的類型將會是更加廣泛而通用的string,這使得我們反而使失去了字面量類型的推導。想要實現(xiàn)上述效果,就需要為string類型賦予“名義”,使它不同于普通的原始類型,不再那么“廣泛”,從而在求并集的時候,不至于被string類型徹底拿捏。附上Typescript Playground。

在Vue中的應用

其實在Vue3源碼中也有很多 Nominal Typing 的例子,例如VNode、Teleport、KeepAliveFragment等等這些內置組件,他們的定義中都有一個標志變量用于區(qū)分。分別對應了__is_VNode,__isTeleport__isKeepAlive,__isFragment。下圖是KeepAlive組件的聲明,更多組件聲明可以移步官方倉庫查閱。

如果類型聲明的位置處在函數(shù)入?yún)⑸?,為了防止與用戶定義的屬性產生沖突,通常會采用unique symbol作為鍵值來構造名義類型,例如:

以上就是TypeScript實用技巧 Nominal Typing名義類型詳解的詳細內容,更多關于TypeScript名義類型Nominal Typing的資料請關注腳本之家其它相關文章!

相關文章

最新評論