--- GA: G-7BSJTG7RYN --- 通常用在[型別化名](https://hackmd.io/@elzuoc/rkcMxJJx3#%E5%9E%8B%E5%88%A5%E5%8C%96%E5%90%8D-Type-Alias)的時候,複合型別包含: `union`:聯集型別 `intersection`:交集型別 首先,這裡所提到的 **聯集** 與 **交集** 的概念,與數學集合論所學到的概念不一樣,想了解可以先跳至 [比較數學集合與型別集合](https://hackmd.io/@elzuoc/rJRtRjUx3#%E6%AF%94%E8%BC%83%E6%95%B8%E5%AD%B8%E9%9B%86%E5%90%88%E8%88%87%E5%9E%8B%E5%88%A5%E9%9B%86%E5%90%88)。 ### 聯集型別 Union Type 將型別進行聯集(`|`),來看個簡單的範例: ```typescript= type Primitives = number | string | boolean | null | undefined; ``` 這代表被註記為 `Primitives` 的變數,可以填入這 5 種型別值之一(`number`, `string`, `boolean`, `null`, `undefined`)。 我們再看一個範例: ```typescript= type NullableSet = null & undefined; ``` 這代表被註記為 `NullableSet` 的變數,可以填入這 2 種型別值之一(`null`, `undefined`)。 > **小知識:** > 在 TypeScript 中,`null`, `undefined` 的聯集結果,稱為**Nullable Types**。 -- #### 互斥聯集 Discriminated Union 在複合型別中,這個方式較為常見。 假設我們有 `UserInfo1`, `UserInfo2` 兩個型別,同時我們建立一個 `UnionUserSet` 型別,它是 `UserInfo1`, `UserInfo2` 的聯集。 ```typescript= type UserInfo1 = { name: string, age: number, }; type UserInfo2 = { hasMobile: boolean, isAdult: boolean, }; type UnionUserSet = UserInfo1 | UserInfo2; ``` 這代表被註記為 `UnionUserSet` 的變數,它的屬性可以是 `UserInfo1` 或 `UserInfo2` 存在的屬性。換個說法,它的屬性僅限於 `UserInfo1`, `UserInfo2` 中存在的屬性。 ![](https://i.imgur.com/TxhoWZE.jpg) 假設宣告一個變數 `setUnion` ,並且註記為 `UnionUserSet`,那麼它的屬性可以是 `name`, `age`, `hasMobile`, `isAdult` 的各種組合。像是: ```typescript= const setUnion: UnionUserSet = { name: 'string', age: 18, hasMobile: false, }; ``` 若給了一個不存在於 `UserInfo1`, `UserInfo2` 的屬性,TypeScript 就會產生錯誤訊息。 ```typescript= const setUnion: UnionSet = { name: 'string', age: 18, hasMobile: false, isCheck: true, // Error }; // Error: Object literal may only specify known properties, and 'isCheck' does not exist in type 'UnionSet'. ``` -- ### 交集型別 Intersection Type 將型別進行交集(`&`),不過這個行為很少見,我們用剛剛的範例來看: ```typescript= type UserInfo1 = { name: string, age: number, }; type UserInfo2 = { hasMobile: boolean, isAdult: boolean, }; type UnionUserSet = UserInfo1 & UserInfo2; ``` 假設宣告一個變數 `setUnion` ,並且註記為 `UnionUserSet`,那麼它的屬性 **必須包含** `name`, `age`, `hasMobile`, `isAdult`,多一個少一個屬性都不行: ```typescript= const setUnion: UnionSet = { name: 'string', age: 18, hasMobile: false, isAdult: true, }; ``` 不過,若有選用屬性,則該屬性用不到時可省略。這個概念類似之後我們會提到的 [**介面擴展(Interface Extension)**](https://hackmd.io/@elzuoc/ryw1Am_xn#%E4%BB%8B%E9%9D%A2%E6%93%B4%E5%B1%95%EF%BC%88Interface-Extension--Interface-Inheritance%EF%BC%89)。 -- ### 數學集合與型別集合的差異 **數學聯集** 與 **型別聯集** > 數學聯集:兩個集合所有屬性都要 > 型別聯集:屬性只要存在於兩個集合之中即可 **數學交集** 與 **型別交集** > 數學交集:只要兩個集合共同都有的屬性 > 型別交集:兩個集合所有屬性都要 直接看比較表: | |數學|型別| |---|---|---| |聯集|兩個集合所有屬性都要|**屬性只要存在於兩個集合之中即可**| |交集|只要兩個集合共同都有的屬性|**兩個集合所有屬性都要**| -- ### Type Guard (尚未有正式的中文譯名) Type Guard 是一種行為的概稱,這個行為是「檢測某變數或表達式的型別」。 事實上,在 JavaScript 我們已經見過它,就是 `typeof` 關鍵字,而且不只它,包含 `Array.isArray()`, `Number.isNaN()`, `Number.isFinite()`, `setNull === null` 都是。 簡單來說,只要某個行為能夠 **正確**「檢測某變數或表達式的型別」,這個行為就稱為 Type Guard。 --- ### Reference - [讓TypeScript成為你全端開發的ACE!- Maxwell Huang](https://www.books.com.tw/products/0010859134) - [讓 TypeScript 成為你全端開發的 ACE! 系列 - 第 11 屆 iThome 鐵人賽](https://ithelp.ithome.com.tw/users/20120614/ironman/2685) - [TypeScript Official Site](https://www.typescriptlang.org/docs) --- > 系列:[`跑完 JS30 就接著認識 TypeScript 入門`](https://hackmd.io/@elzuoc?tags=%5B%22%E8%B7%91%E5%AE%8C+JS30+%E5%B0%B1%E6%8E%A5%E8%91%97%E8%AA%8D%E8%AD%98+TypeScript+%E5%85%A5%E9%96%80%22%5D) > 上一篇:[Day05:型別系統 - Never、Any、Unknown](https://hackmd.io/@elzuoc/Skd3Uree3) > 下一篇:[Day07:型別系統 - 泛用型別 Generic Types](https://hackmd.io/@elzuoc/BJie-0Le3) ###### tags: [`跑完 JS30 就接著認識 TypeScript 入門`](https://hackmd.io/@elzuoc?tags=%5B%22%E8%B7%91%E5%AE%8C+JS30+%E5%B0%B1%E6%8E%A5%E8%91%97%E8%AA%8D%E8%AD%98+TypeScript+%E5%85%A5%E9%96%80%22%5D) ###### Created on ∥ March 21, 2023 ###### 文章若有任何錯誤,還請不吝給予留言指正,謝謝大家!