Try   HackMD

Typescript 泛用型別

tags: Typescript

Table of Contents

泛用型別 X 型別參數化

一、泛用型別

原理跟普通的函式概念差不多,可以把泛用型別看成是型別版的函式

type Identuty<T> = T

泛用型別就是將型別化名進行參數化的動作

1. 任何型別化名都可以轉換成泛用型別

​​​​- 在泛用型別化名的名稱後面接上的 <> 內容就是型別參數(Type Parameter)的宣告。
​​​​- 型別參數可以有複數個,只要在 <> 裡用逗號分隔就可以了。

型別參數可以有複數個,只要在 <> 裡用逗號分隔就可以了。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

在定義 Dictionary 泛型別後,correctDict 變數內的值就必須為布林

type Dictionary<T> = { [prop: string]: T } let correctDict: Dictionary<boolean> = { wentToClub: true, playedMahjong: true, }

2. 宣告函式時就使用泛型

function identityFunc<T>(something: T): T { return something }

如果你呼叫該函式時是 identityFunc<string> 這樣呼叫的,輸入必須填數 string 型別,輸出也是 string 型別。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

3. 將泛型 T 裡面的選用屬性轉成必要屬性

interface PersonalInfo { name: string, age?: number, hasPet?: boolean } let validPerson: PersonalInfo = { name: 'Maxwell', hasPet: true } let incompletePersonalInfo: Required<PersonalInfo> = { name: 'Maxwell', age: 20 }

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

泛型註記 X 推論未來

泛用型別的宣告

型別化名分成三種 ——

  • 型別(Type)
type GT<TP1, TP2, TP3, ...,TPn> = (型別化名內容必須包含 TP1, TP2, TP3, ...,TPn)
  • 介面(Interface)
interface GT<TP1, TP2, TP3, ...,TPn> = (型別化名內容必須包含 TP1, TP2, TP3, ...,TPn)
  • 類別(Class)
class GT<TP1, TP2, TP3, ...,TPn> = (型別化名內容必須包含 TP1, TP2, TP3, ...,TPn)
  • 泛用抽象類別就是在泛用類別旁邊註記 abstract 關鍵字
abstract class GT<TP1, TP2, TP3, ...,TPn> = (型別化名內容必須包含 TP1, TP2, TP3, ...,TPn)

預設型別參數 Default Type Parameter

用等號連結型別值

// 預設型別 type DefaultStringDictionary<T = string> = { [prop: string]: T } // 預設鍵值對的值之型別 string let stringDict: DefaultStringDictionary = { message: 'Hello World', language: 'TypeScript' } // 覆蓋鍵值對的值之型別 boolean let booleanDict: DefaultStringDictionary<boolean> = { hasPet: false, hasMotorcycle: true, }

泛用型別化名的型別參數限制 Type Constraint in Generic Type Alias

某泛用型別化名 GT 之型別參數 Tparam 被限制在某型別 Tcontraint 範圍之下,可以使用 extends 關鍵字,其格式為:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

type Primitives = number | string | boolean | null | undefined type PrimitiveArray<T extends Primitives> = Array<T> let numberPrimitiveArr: PrimitiveArray<number> = [1, 2, 3] let stringPrimitiveArr: PrimitiveArray<string> = ['1', '2', '3'] let numberOrStringPrimitiveArr: PrimitiveArray<number | string> = [1, '2', 3] interface IPersonalInfo { name: string, age: number, hasPet: boolean } // Primitives 中沒有 Object 的 union,TS 會警告錯誤 let invalidObjectArray: PrimitiveArray<IPersonalInfo> = [ { name: 'Maxwell', age: 20, hasPet: false } ]

泛用函式

  • 泛用函式的宣告
    必須要將型別參數馬上宣告在函式名稱的後面。若某函式所擁有的型別參數有 TP1、TP2、、TPn
function F<TP1, TP2, ...,TPn>(/*函數之參數*/): Treturn { /* 函式內容 */ }
  • 藉由隱藏在陣列裡的泛用機制,編譯器早就可以推論出回呼函式的參數型別。
// 泛用函式 function traverseElements<T>( value: Array<T>, callback: (el: T, index: number) => void ) { for (let i = 0; i < value.length; i += 1) { callback(value[i], i) } } // 呼叫函式 let numberArrayInput = [2, 5, 7, 9] let traverseCallback = function(el: number, index: number) { console.log(`Index ${index} - Value ${el}`); } traverseElements<number>( numberArrayInput, traverseCallback ) // 簡化成 traverseElements<number>( [2, 5, 7, 9], (el, index) => { console.log(`Index ${index} - Value ${el}`); } )
  • 泛用型別可以推論未來的型別使用的可能性
    下例中的 Array.prototype.map 可以正確地推論出陣列中的型別

介面與類別 X 泛型註記機制

泛用類別 Generic Class

class C<T> { constructor(public memberProp: T) {} public memberFunc() { return this.memberProp } get value() { return this.memberProp } set value(input: T) { this.memberProp = input } }
  • 不註記變數,建構 c 物件時填入型別參數

泛型別帶入 number,其輸出的成員方法及成員變數也會輸出 number

  • 就算沒有對泛型做積極註解,ts 也會根據參數帶入的值去推導出泛型的型別

  • 泛用型別的繼承
    在 class D 的部分,因為不知道<T>的型別,因此要像 class F 一樣給一個型別

迭代器模式 X 泛用迭代器

迭代器是專門巡訪聚合物的一個物件
聚合物指的是:陣列、列狀物、集合(Set)