Rick's DevNotes
筆記關於我作品集
筆記類別
  • 全部
  • DockerDocker
  • NetworkNetwork
  • RxJSRxJS
  • NginxNginx
  • TypeScriptTypeScript
  • Data_Structure_And_AlgorithmData Structure And Algorithm
  • JavaScriptJavaScript
  • PostgreSQLPostgreSQL
  • ReactReact
  • GitGit

© 2026 Rick's DevNotes. All rights reserved.

# TypeScript# Type# Generics# Class

更新時間:2025/08/04

建立時間:2021/07/18

TypeScript筆記 - Part 2 (Interfaces & Classes & Generics )

Interfaces以及 TypeScript 中的物件

物件作為函式的參數 (argument) 時,需在宣告函式過程進行參數的型別註記,如下方程式碼,函式 printVehicle 引入的物件需要符合{ name: string; year: number; broken: boolean; summary(): string; }條件,然而這樣的方法存在許多缺點如 1. 物件屬性越多,會使程式碼越冗長 2. 同型別的物件被多個函式作為參數引入時,相同的註記又須重複一次。

透過 Interface 避免冗長的 Annotations

對於物件而言,為了在 TypeScript 中可以使程式碼簡潔又重複使用,可以透過 Interface 的幫助描述物件內的 key 名稱及其 value 型別,如下方程式碼,透過宣告 Car interface 來明確定義物件內的型別,並在函式宣告時引入, TypeScript 即可確認函式被呼叫時引入的 argument 是否符合 Car interface 的條件。

滿足 Interface 的條件在於 物件是否含有對應的name與type ,因此物件所多出的 properties 不會影響 TypeScript 的判斷,如下方程式碼中,物件 Tesla 以及物件 PS5 符合 Intro interface 的條件 (都具有summary property) ,因此可以作為函式 printSummary 的參數。


類別 (Classes)

類別 (classes) 是可以作為描述物件的藍圖,在 TypeScript 中,而在 TypeScript 中,可以透過 Modifiers 來明確定義內部的 properties 應當在什麼位置被呼叫

Modifiers

  • public : 允許 property 在任何時間、地點被呼叫。
  • private : 只允許 property 在自身 class 內部被呼叫。
  • protected : 只允許 property 在自身 class 及其子 class 內部被呼叫。

建構子 (Constructor)

一般方式定義 Class 內的 Constructor

可以透過更簡短方式定義 Class 內的 Constructor


通用型別 (Generics)

概念

在編寫程式碼的過程中,若希望寫出的 component 具有高自由度 (適應多種型別)、重複使用 (Reusable) 的特性,可以透過 TypeScript 的通用型別 (Generics) 來達到此目的,其概念類似下方函式 show ,被傳入的 argument 型別與回傳的 value 型別都是 String 。

上述的概念可以透過 any 型別表示,如下方程式碼,任何型別都可以作為 thing 被傳入,然而缺點在於,該函式可以回傳任何型別的 value ,導致我們只能知道傳入的 thing 型別,卻無法得知最後回傳的 value 型別

透過 Gnerics 改善

要改善上述的缺點,可以將 type variable 加入函式之中,即在函式名稱後加入< T >,其作用可想像將 T 作為 argument 傳入函式,在呼叫過程,TypeScript就會檢視被T所標記的任何事物 (eq:thing) ,因此回傳的 value (thing) 也必須是 T 型別。

在完成 generic function 後,有兩種方法可以進行呼叫

  • 第一種方式: 直接將 type argument 傳入函式之中, TypeScript Compiler 檢視回傳的 value 是否符合的 type argument 的條件
  • 第二種方法: 透過 Type Inference 協助, TypeScript Compiler 直接檢視 argument(thing) 的型別,並將 T 推斷為與其相同的型別。

< T > 內部的 T 可以是任何名稱 (Type、Tp...) ,可依照個人 (團隊) 使用習慣變更

Generics (泛型) 函式運用實例

下方程式碼中,函式 listMemberName 以及函式 listMemberAge 都可列出陣列內的資料,其差異僅在於列出的資料是字串陣列或是數字陣列,為了讓程式碼更簡潔、彈性,可以宣告一個 generic function (listInfo) 來避免程式碼內容重複性高的函式出現。

  • 兩個函式的內容重覆,僅在於回傳陣列之型別不同
  • 將兩種內容重複的函式內容透過 generic function 表現

使用 Arrow Function 搭配 Generics

這是最基本的泛型函式:傳入什麼,就回傳什麼。

函式可針對不同型別的陣列進行處理:

使用 extends 限制泛型的條件(此處要求必須包含 .length 屬性):

泛型函式也可以用來處理物件屬性

為什麼 <T,> 要加逗號? 在 arrow function + generic 的語法中,若省略逗號,TypeScript 在某些情境(如 React 環境)會把 <T> 誤判為 JSX 元素,導致語法錯誤。因此建議寫成 <T,>。

Generics 延伸至 Classes 的運用

  • 類別 MemberAgeList 及類別 MemberNameList 內容重複性高
  • 將兩種內容重複的類別透過 Generic Class 表現

通用型別的條件約束 (Generic Constraints)

在定義 generic function 可能會遇到下方的程式碼異常,如下方的 gameRoom function ,TypeScript僅知道傳入的 argument (arr) 是一個T型別的陣列,但無法明確知道 arr 是否有 bootUp 的 property ,因此跳出了警告標語。

為了解決該異常,可以透過限制 (constraint) 的方式,告知該函式傳入的 T 型別必須要具有 bootUp 的 property ,如下方程式碼中,宣告了一個具有 bootUp property 的greet Interface ,並在 gameRoom 內透過 extends 方式來表現對 generic function 的限制。

在限制中多加一層限制的 Generic constraint

為了避免存取物件內的 property 時出現該 property 不存在的情況,如下方程式碼,可以透過 extends keyof 以確保型別K必須是型別 T 的 property 之一。

參考資料

  • Typescript : The Complete Developer's Guide