---
# System prepended metadata

title: Typescript 學習

---

# Typescript 特色

* JavaScript 的一種超集
* 強型別
* 支援可選的靜態類型
* 支援介面（Interface）
* 支援泛型（Generics）
* 支援枚舉（Enum）
* 使用自動垃圾回收（Garbage Collection）來管理記憶體

---
# 基本語法

## Variable & Constant (變數和常數)
* **名稱字元**

1. 字母：A-Z，a-z
2. 數字：0-9 (不能以數字開頭)
3. 底線：_

* **命名規則**

**1. Camel Case (駝峰式命名)**
> userName
> fileName

**2. Snake Case (Snake Case 命名法)**
> user_name
> file_name

**3. Pascal Case (帕斯卡式命名)**
> UserName
> FileName

![1](https://hackmd.io/_uploads/ry_8OJsva.png)
* 變數可以加型別也可以不加型別
* 常數不可以賦值後另外再改變
![image](https://hackmd.io/_uploads/HJwgvkiPT.png)

---
## Variable (變數類型)
![2](https://hackmd.io/_uploads/HJFKnJiPp.png)
* number: 數字，包括整數和浮點數。
* string: 字符串。
* boolean: 布林值，只能是 true 或 false。
* null: 表示缺少值或空值。
* undefined: 表示未初始化的值。
* any: 表示一個變數可以是任何類型。
* Union Types: 聯合類型，允許一個變數具有多種可能的類型。
* Template Strings: ${}模板字符串: 允許在字符串中插入變數或表達式

![image](https://hackmd.io/_uploads/H1D2a1sPa.png)

---
## Operator (運算子)
**1. 算術運算子：**
* +：加法
* -：減法
* *：乘法
* /：除法
* %：取餘

**2. 關係運算子：**
* ==：等於
* ===：嚴格等於(型別也會判斷)
* !=：不等於
* !==：嚴格不等於(型別也會判斷)
* \>：大於
* <：小於
* \>=：大於等於
* <=：小於等於

**3. 邏輯運算子：**
* &&：邏輯與（AND）
* ||：邏輯或（OR）
* !：邏輯非（NOT）

**4. 位元運算子：**
* &：位元與
* |：位元或
* ^：位元異或
* ~：位元非
* <<：左位移
* \>>：右位移

**5. 賦值運算子：**
* =：賦值
* +=、-=、*=、/=、%=：複合賦值

**6. 三元運算子：**
* condition ? expr1 : expr2：
如果 condition 為真，返回 expr1，否則返回 expr2

---
## Enum (枚舉)
![3](https://hackmd.io/_uploads/S1UYxxsw6.png)
* enum: 為一組相關的常數提供了一個有意義的名稱，使程式更具可讀性。
* 默認從0開始也可以自己賦值
* type: 用於定義新的類型，能夠為現有的類型創建一個別名。

![image](https://hackmd.io/_uploads/B1KW-loPa.png)

---
## Array(陣列)
![9](https://hackmd.io/_uploads/SyIC5TCPp.png)
* let numbers: number[] : 定義一個包含數字的陣列
* let numbers: Array<int> : 使用 Array<T> 語法
* numbers.**push**(x) : 將一個或多個元素添加到陣列的末尾。
* numbers.**pop**() : 刪除陣列的最後一個元素。
* numbers.**shift**() : 刪除陣列的第一個元素。
* numbers.**unshift** (x) : 將一個或多個元素添加到陣列的開頭。
* numbers.**slice**(x, y) : 返回陣列[x, y-1]
* numbers.**splice**(x, y) :  從索引 x 開始刪除 y 個元素。
* numbers.**reverse**() : 反轉陣列的順序。
* numbers.**sort**() : 對陣列的元素進行排序。
* numbers.**indexOf**(x) : 返回指定元素x的索引，如果找不到則返回 -1。
* arr1.**concat**(arr2) : 連接兩個或多個陣列，返回一個新陣列。

---
## Generics (泛型)
1. **代碼重用和靈活性**：允許編寫能夠適用於多種類型的代碼，而不必針對每種類型編寫重複的邏輯。這使得代碼更具重用性和靈活性。
2. **類型安全**：提供了一種在編譯時檢查類型的機制，避免了在運行時由於類型錯誤導致的問題。這有助於提高代碼的可靠性和維護性。
3. **抽象數據結構和算法**：可以創建抽象的數據結構和算法，而不必關心實際的數據類型。
4. **與現有庫和框架的兼容性**：可以更容易地與現有的庫和框架進行集成，以處理各種類型的數據。
5. **更清晰的API設計**：可以用於設計更清晰和通用的 API，使得 API 更易於理解和使用。
![15](https://hackmd.io/_uploads/HyhRwlkdp.png)

---
## For Loop Iteration (迴圈迭代)
![4](https://hackmd.io/_uploads/Hyqs9eoDp.png)

* for...in: 用於迭代對象的index
* for...of: 用於迭代對象的值
* forEach: 對每個元素都應用指定的回調函數。這個回調函數接收三個參數，分別是：
1. 元素的值（value）： 陣列中當前遍歷的元素的值。
2. 元素的索引（index）： 陣列中當前遍歷的元素的索引。
3. 原始陣列（array）： 正在遍歷的陣列本身。

---
## Function (函式)
![5](https://hackmd.io/_uploads/r16hf-oDT.png)

**1. 函數宣告（Function Declaration）：**
* **特點**：提供一個具名函數，可以在任何地方使用。
* **適用情境**： 通常在整個scope中都需要使用函數時使用。

**2. 函數表達式（Function Expression）：**
* **特點**：使用變數賦值給一個函數，函數可以匿名也可以命名。
* **適用情境**： 如果函數僅在特定的區塊或運算中使用，可以使用函數表達式。

**3. 箭頭函數（Arrow Function）：**
* **特點**：簡潔的函數表達式，它使用 => 語法。
* **適用情境**： 當函數只有一行時，且不需要使用 this。

**4. 選擇性參數（Optional Parameters）：**
* **特點**：使用 ? 來表示，允許在函數調用時不提供該參數，這樣該參數將被視為undefined。
* **適用情境**： 當某個參數可能存在但不一定需要被提供時使用。

**5. 默認參數（Default Parameters）：**
* **特點**：直接在函數聲明中給定初始值，當該參數在函數調用時未提供值時，將使用默認值。
* **適用情境**： 當某個參數通常有一個常見的默認值時使用。

**6. 剩餘參數（Rest Parameters）：**
* **特點**： 可以處理不定數量的附加參數，將它們收集到一個陣列中。
* **適用情境**： 當函數需要接受可變數量的參數時使用。

---
## Callback function (回調函式)
* **非同步操作**： 用於處理非同步操作，例如檔案讀取、網路請求、計時器等。 當非同步操作完成時，回調函數被呼叫以處理結果。
* **事件處理**： 在事件驅動的程式設計中，回呼函數通常用於處理特定的事件，例如按鈕點擊、滑鼠移動等。 當事件發生時，相關的回調函數被呼叫。
* **靈活性**： 透過回呼函數，可以將某些特定的行為（程式碼邏輯）傳遞給函數，使得函數能夠在不同的上下文中執行不同的操作。
* **參數傳遞**： 回呼函數通常接受一定數量的參數，這些參數包含在呼叫回呼函數的上下文中，以便在回呼函數內部使用。
* **錯誤處理**： 回呼函數也可以用來處理錯誤，例如在非同步操作中，當出現錯誤時，可以呼叫特定的錯誤處理回呼函數。
![10](https://hackmd.io/_uploads/Hy4cMR0Pp.png)


---
## Asynchronous function (非同步函式)
* **非同步** : 同步的程式語言遇到非同步的事件時，會將非同步的事件移動到程式碼的最後方，等到所有的原始碼運行完以後才會執行非同步的事件。
* **Promise** : 是用來優化非同步的語法結構，
* **Async、Await** : 可以基於 Promise 讓非同步的語法的結構類似於 “同步語言”，更易讀且好管理。
### Promise
* **什麼是 Promise？**
**Promise** 是 JavaScript 或 TypeScript 中用於處理異步操作的一個對象。它代表了一個可能在未來完成或失敗的操作，並提供一個統一的、可預測的方式來處理這些操作的結果。
**Promise** 本身是一個**建構函式**，函式也是屬於物件的一種，因此可以附加其它屬性方法在上
![image](https://hackmd.io/_uploads/BkDh1hRwp.png)
* Promise 建構函式建立同時，必須傳入一個函式作為參數（executor function），此函式的參數包含 **resolve**, **reject**，這兩個方法分別代表成功與失敗的回傳結果，特別注意這兩個僅能回傳其中之一，回傳後表示此 Promise 事件結束。
* **Promise 的狀態：**
**Pending** (進行中)：Promise 的初始狀態，表示操作尚未完成。
**Fulfilled** (成功)：表示操作成功完成，並返回一個resolve結果。
**Rejected** (失敗)：表示操作未成功完成，並返回一個rejected錯誤。
![7](https://hackmd.io/_uploads/H1uASfjv6.png)
* **Resolve & Reject**
這兩個函數是由 Promise 的執行體（executor）中提供的回調函數所接收的，它們用於將 Promise 從未定（pending）的狀態轉換為已解決（fulfilled）或已拒絕（rejected）的狀態。
* **.then() & .catch()**
.then() 方法用於處理 Promise 成功的情況。它接受一個或兩個回調函數作為參數
.catch() 方法用於處理 Promise 失敗的情況。它接受一個回調函數作為參數，這個回調函數處理 reject 函數中傳遞的錯誤。
### Async/Await
* **什麼是 Async/Await？**
**async/await** 是 JavaScript 中處理異步操作的一種語法，它使得異步程式碼的撰寫和理解更加簡單。它建立在 Promise 的基礎上，提供了一種更同步風格的編碼方式。
* **簡化異步程式碼**： **async/await** 語法簡化了異步程式碼，使其看起來更像同步程式碼，提高了可讀性。
* **同步風格的錯誤處理**： 使用 **try/catch** 塊可以方便地捕獲異步操作中的錯誤，提供更優雅的錯誤處理機制。
![8](https://hackmd.io/_uploads/B1jtX6CwT.png)
* **async function** : 可以用來定義一個非同步函式，讓這個函式本體是屬於非同步，但其內部以“同步的方式運行非同步”程式碼。
* **await** : await 是屬於一元運算子，它會直接回傳後方表達式的值；但如果是 Promise 時則會暫停非同步函式的運行（中止 Promise 的運行），直到非同步進入 resolve 或 reject，當接收完回傳值後繼續非同步函式的運行。
* 參考資訊 : 
[JavaScript Promise 全介紹](https://www.casper.tw/development/2020/02/16/all-new-promise/)
[Async function / Await 深度介紹](https://www.casper.tw/development/2020/10/16/async-await/)

---
## export & import (導出和導入)
* 在TypeScript中，使用**export**和**import**語句來定義模塊（Module），這使得代碼可以分割成多個文件，提高代碼的可維護性和可讀性。
* **export** : 用於將變量、函數、類或模塊進行導出，使其可以在其他文件中使用。
    1. **named export（命名導出）**：導出前必須給予特定名稱，而導入時也必須使用相同的名稱。另外，**一個檔案中可以有多個** named export。
    2. **default export（預設導出）**：**一個檔案僅能有唯一的** default export，而此類型不需要給予名稱。
* **import** : 用於導入模塊中的變量、函數、類等。
* **default** 關鍵字通常用於模組系統（Module System）。模組是一種組織和封裝 TypeScript 程式碼的方式，使其可以被其他程式碼引入和重複使用。
* 想**重新命名**導入(導出)的變數、函數、或類，可以使用 as 關鍵字指定一個新的名稱。
![16](https://hackmd.io/_uploads/BJB2OJlup.png)

---
# OOP (物件導向)
* **Class、Object、Method、Property**：
    * **Class (類別)**： 一種抽象的數據類型，描述了物件的屬性和行為。
    * **Object (物件)**： 類別的實例，具有屬性和方法。。
    * **Method (方法)**： 與類別或對象相關聯的函數。
    * **Property (屬性)**： 與類別或對象相關聯的變數。
1. **Encapsulation (封裝)**：
    * 將數據和相關的操作（方法）封裝在一個單位（類別）中的概念。
    * 類別通常提供 **公開（public）、私有（private）和受保護（protected）** 等不同層次的訪問權限。
2. **Inheritance (繼承)**：
    * 一種類別之間的關係，允許一個類別（子類別）繼承另一個類別（父類別）的屬性和方法。
    * 有助於重用代碼並建立層次結構，子類別可以擁有父類別的特性並添加自己的功能。
3. **Polymorphism (多型)** : 表示同一類型的物件可以在不同的情況下表現出不同的行為。多型主要有以下三種形式：
    1. **Parametric Polymorphism (參數多型)** ： 一種泛型（Generic）的形式，可以使函數或類別在操作不同型別的數據時保持彈性。
    2. **Subtype Polymorphism (子類型多型)** ： 繼承和介面實現的一種形式，允許父類型的變數引用子類型的實例，並以多態的方式呼叫方法。
    3. **Operator Overloading Polymorphism (運算子多型)** ： 一種使運算子具有不同行為的能力，取決於操作的物件類型。

## Constructor & Static (建構式和靜態)
* **Constructor (構造函數)**： 一個特殊的方法，在創建類別的實例時被調用。它通常用來初始化類別的成員屬性，以及執行一些額外的初始設定。
* **Access Modifiers (存取修飾符)**： TypeScript 提供了三種存取修飾符，分別是 public、private 和 protected，用來控制成員的可訪問性。
* **Member Properties (成員屬性)** : 定義在類別中的變數，用來描述物件的狀態。它們通常在類別的構造函數中進行初始化，並且可以在整個類別中被訪問。
* **Member Methods (成員方法)**: 定義在類別中的函數，用來定義類別的行為。它們可以訪問類別的成員屬性，並執行一些操作。
* **Static Properties (靜態屬性)** : 屬於類別本身而不是類別的實例。這些屬性在整個類別的生命週期中只存在一份，並且可以直接透過類別名稱訪問，而不需要實例化類別。
* **Static Members (靜態成員)**： 屬於類別本身而不是實例，可以通過類別名直接訪問。使用 static 關鍵字聲明靜態成員。
![11](https://hackmd.io/_uploads/rkB6dCRwa.png)

---
## Destructor(解構式)
* TypeScript（以及JavaScript）中，並沒有像某些其他語言（例如C++）中的 "Destructor" 概念。在JavaScript和TypeScript中，內存管理由垃圾回收器（Garbage Collector）負責，開發者不需要手動釋放內存或定義類似於 "Destructor" 的方法。
* **垃圾回收器** : 負責追蹤不再使用的對象並釋放相應的內存。在JavaScript和TypeScript中，物件不再被引用時，它將被標記為"可回收"，並在垃圾回收器執行時進行釋放。
* 在類別中，如果有一些資源需要手動釋放（例如關閉連接、清理計時器等），開發者通常會提供一個 destroy 或 dispose 方法

---
## Inheritance (繼承)

* **Inheritance (繼承)** : 允許一個類別（子類別）使用另一個類別（父類別）的屬性和方法。子類別可以繼承父類別的特性，同時還可以擴展或修改這些特性。
* **extends** : 用於建立類別之間的繼承關係。當一個類別（子類別）需要使用另一個類別（父類別）的屬性和方法時，可以使用 extends 來建立繼承。
* **super** : 用於呼叫父類別（或父類別的原型）的屬性和方法。它通常用於子類別的構造函數中，以調用父類別的構造函數。
![12](https://hackmd.io/_uploads/HJdnw11_a.png)

---
## Abstract & Interface (抽象和介面)
### Abstract VS Interface
* **Abstract Class (抽象類別)** ：
    1. 可以包含實際的實作程式碼，可以有實例屬性和實例方法。
    2. 透過 **abstract** 關鍵字定義，可以包含抽象方法（方法沒有實際實現，必須在衍生類別中實現）。
    3. 一個類別只能繼承自**一個**抽象類別。
* **Interface (介面)** ：
    1. 不能包含實際的實作程式碼，只能包含屬性和方法的定義。
    2. 透過 **interface** 關鍵字定義。
    3. 一個類別可以實作**多個**介面。
* **Extends**
    1. 類別繼承
    2. 介面繼承
### Abstract
* **Abstract Class (抽象類別)**:
    1. **抽象類別不能被實例化**： 抽象類別主要用於被繼承，不能直接創建實例
    2. **抽象類別可以包含實現的方法**： 除了抽象成員外，抽象類別可以包含實現的方法。
* **Abstract Members (抽象成員)**:
    1. **抽象成員必須在派生類別中實現**： 派生類別（子類別）必須提供抽象類別中聲明的抽象成員的實現。
    2. **抽象成員不能包含實現**： 抽象成員只能在抽象類別中聲明，而不能包含實際的實現。
    3. **派生類別必須實現所有抽象成員**： 如果派生類別沒有實現抽象類別中聲明的所有抽象成員，則該派生類別本身也必須標記為抽象。
![13](https://hackmd.io/_uploads/r1tIwyJu6.png)

### Interface
* **implements** : 用於類別實現（implement）一個或多個介面。該類別將提供介面中定義的所有成員，包括屬性和方法。
1. **實現單個介面**：使用 implements 來表示一個類別實現一個介面。
2. **實現多個介面**：一個類別可以同時實現多個介面，使用逗號分隔介面名稱。
3. **類別繼承和介面實現的同時存在**：一個類別可以同時繼承另一個類別並實現一個或多個介面。先繼承再實現，使用 extends 和 implements。
![14](https://hackmd.io/_uploads/By95Gxk_6.png)

# Design Pattern (設計模式)
1. 建立型模式
2. 結構型模式
3. 行為型模式
4. 併發型模式

## Singleton Pattern (單例模式)
* **Singleton Pattern (單例模式)**: 一種創建型設計模式，確保某個類別只有一個實例，並提供一個全局訪問點。在需要共享資源、限制特定類型的實例數量或確保唯一性的情況下非常有用。
1. **私有構造函數**： 通過將構造函數標記為私有，防止直接通過 new 關鍵字創建實例。
2. **私有靜態實例**： 使用一個私有靜態成員（instance）來保存實例，並確保只有一個實例。
3. **靜態方法 getInstance**： 這個方法負責創建實例，如果還沒有創建過的話。在這個方法中，首先檢查 instance 是否存在，如果不存在則創建一個新的實例。
4. **使用時的唯一性**： 通過 getInstance 方法獲取實例，確保每次獲取的都是同一個實例。
![17](https://hackmd.io/_uploads/rJE3iygu6.png)

---
## ...To Do



