--- GA: G-7BSJTG7RYN --- 泛用型別可以視為是將 [型別化名](https://hackmd.io/@elzuoc/rkcMxJJx3#%E5%9E%8B%E5%88%A5%E5%8C%96%E5%90%8D-Type-Alias) 進行 **參數化** 的行為,任何型別都可以轉換成泛用型別。目的是為了讓 **型別化名** 能更彈性的運用。 簡單看個範例: ```typescript= type Identity<T> = T; ``` 在 `Identity<T>` 中的 `T`,我們視為是`泛用型別` 宣告時的參數,稱為**型別參數(Type Parameter)**。 若還是很難懂,可以想成 `函式` 宣告時的參數 `function call(T){}`,呼叫時可以帶入各種變數值。 ```typescript= function callFunction(T) { return T; } const str = 'string'; callFunction(str); ``` 但使用泛用型別時,型別參數只能放入型別,像是 `number`, `string` 等其他篇章提及的型別。 ```typescript= type Identity<T> = T; let beNumber: Identity<number>; ``` 當我們將 `T` 取代成 `number`,則 `Identity<number>` 的結果就會是 `number`。 ### 內建的泛用型別 Built-in Generics 陣列型別 - `Array<T>`,這是內建的泛用型別,等同於 `T[]`。可以想成內建已經先將陣列宣告進行型別化名。 ```typescript= type Array<T> = T[]; ``` ### 條件型別 Conditional Types 還記得我們在 [<Day04:型別系統 - 明文型別 Literal Type 與 型別化名>](https://hackmd.io/@elzuoc/rkcMxJJx3) 的最後有談過 [選用屬性](https://hackmd.io/@elzuoc/rkcMxJJx3#%E9%81%B8%E7%94%A8%E5%B1%AC%E6%80%A7-Optional-Properties) 嗎? 而條件型別最常見的是 `Required<T>` ,它可以將所有 `T` 中的選用屬性,轉為必要屬性。 我們用之前的範例來看: ```typescript= type Member = { name: string, age: number, birthday?: Date, }; ``` 接著我們使用 `Required<T>`: ```typescript= let memberInfo: Required<Member> = { name: 'Connie', age: 18, }; ``` 若沒有使用 `Required` ,這段語法可以正常運作,因為 `birthday` 是選用屬性。但當我們使用 `Required<T>`,就會強制將 `birthday` 轉為必要屬性。 ### 泛用化名 Generic Type Alias 除了型別(Types),函式(Function)、介面(Interface)與類別(Class),也都可轉換成泛用型式。 以型別為例,我們若將 `T` 帶入 `boolean`,但實際上屬性 `name` 的型別是 `string`,TypeScript 就會顯示警告: ```typescript= type Dictionary<T> = { [prop: string]: T // 此處使用到索引型別的技巧 }; let dict: Dictionary<boolean> = { name: 'string' } ``` 通常要針對函式做型別化名,會有一種特質,**輸入參數** 與 **返回值** 型別一致: ```typescript= type operator<T> = (p1: T, p2: T) => T; ``` 我們也可以在宣告函式時,宣告為泛用形式: ```typescript= function identityFunc<T>(params: T): T { return params; } ``` ```typescript= interface LinkedList<T> { head: LinkedListNode<T> | null; length: number; at(index: number): LinkedListNode<T> | null; }; interface LinkedListNode<T> { value: T; next: LinkedListNode<T> | null; } ``` ```typescript= class TypedArray<T> { constructor(public value: T[]) {} } ``` --- ### 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) > 上一篇:[Day06:型別系統 - 複合型別 Composite Types](https://hackmd.io/@elzuoc/rJRtRjUx3) > 下一篇:[Day08:型別系統 - 索引型別 Indexable Types](https://hackmd.io/@elzuoc/Hyf-oGue2) ###### 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 ###### 文章若有任何錯誤,還請不吝給予留言指正,謝謝大家!
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up