TypeScript Learning

TypeScript 是什麼?

⏱️預計 40 分鐘
📖TypeScript 課程
🎯實戰導向

第 1 課:TypeScript 是什麼?

學習目標

  • 理解 TypeScript 嘅基本概念以及佢同 JavaScript 之間嘅關係
  • 明白點解要學習 TypeScript,以及佢嘅主要優勢
  • 體驗 TypeScript 嘅基本類型註解
  • 學會使用互動編輯器進行簡單練習

1. TypeScript 簡介

TypeScript 其實係 JavaScript 嘅一個「超集」(superset)。意思即係,任何有效嘅 JavaScript 程式碼都係有效嘅 TypeScript 程式碼,但 TypeScript 喺 JavaScript 嘅基礎上,加入咗一啲額外嘅功能,最重要嘅就係「靜態類型系統」(static type system)。

TypeScript 嘅歷史同背景

TypeScript 係由 Microsoft 喺 2012 年開發嘅開源程式語言。當時 JavaScript 雖然功能強大,但缺乏類型檢查,令大型專案變得難以維護。TypeScript 嘅出現就係為咗解決呢個問題。

發展歷程:

  • 2012年:Microsoft 發布 TypeScript 0.8
  • 2014年:TypeScript 1.0 正式發布
  • 2016年:Angular 2 採用 TypeScript 作為主要開發語言
  • 2020年:TypeScript 4.0 發布,功能更加完善
  • 現在:被廣泛應用於各種大型專案

靜態類型 vs 動態類型

動態類型(JavaScript):

  • 變數嘅類型喺執行時才確定
  • 靈活但容易出錯
  • 錯誤通常喺執行時先發現

靜態類型(TypeScript):

  • 變數嘅類型喺編寫時就確定
  • 較嚴格但更安全
  • 錯誤喺編寫時就可以發現

JavaScript vs TypeScript 對比

typescript
1// JavaScript - 動態類型,執行時才知道問題
2let message = "Hello, JavaScript!";
3message = 100; // 完全冇問題,但可能引致後續問題
4console.log(message.toUpperCase()); // 執行時先會爆錯!
5
6// TypeScript - 靜態類型,寫程式碼時就發現問題
7let messageTS: string = "Hello, TypeScript!";
8// messageTS = 100; // TypeScript 編譯器會即刻報錯
9console.log(messageTS.toUpperCase()); // 安全!

TypeScript 嘅編譯過程

TypeScript 唔係直接執行嘅,而係需要「編譯」(compile)成 JavaScript:

plaintext
1TypeScript 程式碼 (.ts) → TypeScript 編譯器 (tsc) → JavaScript 程式碼 (.js)

呢個過程中,TypeScript 編譯器會:

  1. 檢查類型錯誤:確保所有變數同函式嘅類型都正確
  2. 移除類型註解:因為 JavaScript 唔理解類型註解
  3. 轉換新語法:將較新嘅 JavaScript 語法轉換為較舊版本
  4. 生成 JavaScript:輸出可以喺瀏覽器或 Node.js 執行嘅程式碼

🎯 互動練習 1:執行你嘅第一個 TypeScript 程式

2. 點解要學 TypeScript?

主要優勢

🔍 及早發現錯誤 TypeScript 可以喺你寫程式碼嘅時候就發現好多錯誤,而唔係等到程式執行時

📖 程式碼更清晰 類型註解令其他人(包括未來嘅你)更容易理解程式碼

🔧 更好嘅開發體驗 編輯器可以提供更準確嘅自動完成和提示

🏗️ 適合團隊合作 清晰嘅類型定義減少團隊成員之間嘅誤解

詳細優勢分析

1. 類型安全(Type Safety)

喺 JavaScript 中,以下程式碼係完全合法嘅,但會導致執行時錯誤:

javascript
1// JavaScript - 潛在問題
2function calculateArea(width, height) {
3  return width * height;
4}
5
6// 呢啲調用都唔會報錯,但結果可能唔係你想要嘅
7calculateArea("10", "20");     // 結果係 "1020" (字串連接)
8calculateArea(10);             // 結果係 NaN (height 係 undefined)
9calculateArea(10, 20, 30);     // 忽略第三個參數

喺 TypeScript 中,呢啲問題會喺編寫時就被發現:

typescript
1// TypeScript - 類型安全
2function calculateArea(width: number, height: number): number {
3  return width * height;
4}
5
6// 呢啲調用會立即報錯
7// calculateArea("10", "20");     // 錯誤:參數類型不匹配
8// calculateArea(10);             // 錯誤:缺少參數
9// calculateArea(10, 20, 30);     // 錯誤:參數過多

2. 更好嘅 IDE 支援

TypeScript 提供咗豐富嘅開發工具支援:

  • 智能提示:編輯器知道變數嘅類型,可以提供準確嘅方法建議
  • 自動重構:安全地重命名變數、函式等
  • 跳轉定義:快速跳轉到函式或變數嘅定義位置
  • 錯誤提示:即時顯示類型錯誤

3. 大型專案嘅可維護性

隨著專案規模增大,TypeScript 嘅優勢更加明顯:

  • 介面定義:清楚定義物件嘅結構
  • 模組系統:更好嘅程式碼組織
  • 重構安全:修改程式碼時減少破壞其他部分嘅風險

實際應用場景

企業級應用

  • Microsoft Office Online:Microsoft 自己嘅產品大量使用 TypeScript
  • Slack:團隊協作工具,處理複雜嘅即時通訊邏輯
  • Airbnb:房屋租賃平台,管理大量用戶數據

開源專案

  • Angular:Google 開發嘅前端框架
  • Vue 3:流行嘅前端框架,核心用 TypeScript 重寫
  • VS Code:Microsoft 嘅程式碼編輯器

學習 TypeScript 嘅投資回報

短期收益:

  • 減少除錯時間
  • 提高程式碼質量
  • 更好嘅開發體驗

長期收益:

  • 更容易維護嘅程式碼
  • 團隊協作更順暢
  • 職業發展機會增加

實際例子:函式類型安全

typescript
1// JavaScript 函式 - 不清楚參數類型
2function greetJS(name, age) {
3  return `Hello ${name}, you are ${age} years old`;
4}
5
6// TypeScript 函式 - 清楚知道參數類型
7function greetTS(name: string, age: number): string {
8  return `Hello ${name}, you are ${age} years old`;
9}
10
11// 更複雜嘅例子:處理用戶資料
12interface User {
13  id: number;
14  name: string;
15  email: string;
16  isActive: boolean;
17}
18
19function processUser(user: User): string {
20  if (!user.isActive) {
21    return `User ${user.name} is inactive`;
22  }
23  return `Processing user: ${user.name} (${user.email})`;
24}
25
26// 使用時,編輯器會檢查物件結構
27const user: User = {
28  id: 1,
29  name: "小明",
30  email: "xiaoming@example.com",
31  isActive: true
32};
33
34console.log(processUser(user));

🎯 互動練習 2:體驗類型錯誤檢測

3. TypeScript 嘅基本類型

TypeScript 有幾種基本類型,我哋先認識最常用嘅:

typescript
1// 基本類型範例
2let myString: string = "Hello";        // 字串
3let myNumber: number = 42;             // 數字
4let myBoolean: boolean = true;         // 布林值
5let myArray: number[] = [1, 2, 3, 4, 5]; // 數字陣列

詳細類型介紹

1. 基本類型(Primitive Types)

字串(string)

typescript
1let firstName: string = "小明";
2let lastName: string = '李';
3let fullName: string = `${firstName} ${lastName}`; // 模板字串

數字(number)

typescript
1let decimal: number = 6;
2let hex: number = 0xf00d;        // 十六進制
3let binary: number = 0b1010;     // 二進制
4let octal: number = 0o744;       // 八進制
5let big: number = 100_000_000;   // 數字分隔符

布林值(boolean)

typescript
1let isDone: boolean = false;
2let isActive: boolean = true;

2. 陣列類型(Array Types)

typescript
1// 兩種寫法都可以
2let list1: number[] = [1, 2, 3];
3let list2: Array<number> = [1, 2, 3];
4
5// 字串陣列
6let fruits: string[] = ["蘋果", "橙", "香蕉"];
7
8// 混合類型陣列(使用 union types)
9let mixed: (string | number)[] = ["hello", 42, "world"];

3. 特殊類型

any - 任何類型

typescript
1let notSure: any = 4;
2notSure = "maybe a string instead";
3notSure = false; // 都可以,但失去了類型檢查

void - 無返回值

typescript
1function warnUser(): void {
2  console.log("This is my warning message");
3}

null 同 undefined

typescript
1let u: undefined = undefined;
2let n: null = null;

4. 物件類型(Object Types)

基本物件

typescript
1let person: { name: string; age: number } = {
2  name: "小華",
3  age: 25
4};

介面(Interface)

typescript
1interface Student {
2  id: number;
3  name: string;
4  grade: number;
5  isActive?: boolean; // 可選屬性
6}
7
8let student: Student = {
9  id: 1,
10  name: "小明",
11  grade: 85
12  // isActive 係可選嘅,可以唔提供
13};

5. 函式類型(Function Types)

typescript
1// 函式聲明
2function add(x: number, y: number): number {
3  return x + y;
4}
5
6// 函式表達式
7let myAdd = function(x: number, y: number): number {
8  return x + y;
9};
10
11// 箭頭函式
12let myAdd2 = (x: number, y: number): number => x + y;
13
14// 函式類型變數
15let myAddFunc: (x: number, y: number) => number;
16myAddFunc = add;

6. 聯合類型(Union Types)

typescript
1// 變數可以係多種類型之一
2let id: string | number;
3id = "ABC123";  // 可以
4id = 123;       // 也可以
5// id = true;   // 錯誤:boolean 唔係允許嘅類型
6
7function printId(id: string | number) {
8  if (typeof id === "string") {
9    // 喺呢個區塊,TypeScript 知道 id 係 string
10    console.log(id.toUpperCase());
11  } else {
12    // 喺呢個區塊,TypeScript 知道 id 係 number
13    console.log(id.toFixed(2));
14  }
15}

7. 類型別名(Type Aliases)

typescript
1// 為複雜類型創建別名
2type StringOrNumber = string | number;
3type User = {
4  id: number;
5  name: string;
6  email: string;
7};
8
9let userId: StringOrNumber = "user123";
10let currentUser: User = {
11  id: 1,
12  name: "小明",
13  email: "xiaoming@example.com"
14};

類型推斷(Type Inference)

TypeScript 好聰明,好多時候唔需要明確指定類型:

typescript
1// TypeScript 會自動推斷類型
2let message = "Hello"; // 推斷為 string
3let count = 42;        // 推斷為 number
4let isReady = true;    // 推斷為 boolean
5
6// 函式返回值也會被推斷
7function getLength(s: string) {
8  return s.length; // 推斷返回 number
9}

類型斷言(Type Assertions)

有時候你比 TypeScript 更清楚某個值嘅類型:

typescript
1// 使用 as 語法
2let someValue: any = "this is a string";
3let strLength: number = (someValue as string).length;
4
5// 或者使用尖括號語法(但喺 JSX 中唔建議)
6let strLength2: number = (<string>someValue).length;

🎯 互動練習 3:建立你嘅個人資料

重點:

  • 每個變數都要符合指定嘅類型
  • string 要用引號包住
  • number 直接寫數字
  • boolean 只能係 truefalse
  • 陣列用方括號 [] 包住元素

4. 函式同類型

函式係程式設計嘅重要部分,TypeScript 可以幫我哋確保函式嘅輸入同輸出都係正確嘅類型。

typescript
1// 函式類型範例
2function add(a: number, b: number): number {
3  return a + b;
4}
5
6function sayHello(name: string): string {
7  return "Hello, " + name + "!";
8}

🎯 互動練習 4:完成函式實作

重點:

  • 函式要返回正確嘅類型
  • add 函式做數學加法
  • greet 函式組合字串
  • introduce 函式將名字同年齡組合成句子

5. 綜合練習

🎯 互動練習 5:寵物資料管理

重點:

  • 變數值要完全符合預期輸出
  • 函式要準確組合字串
  • 注意中文字符同標點符號
  • 函式參數嘅順序要正確

6. TypeScript 開發環境同工具

TypeScript Playground 介紹

TypeScript Playground 係一個線上工具,你可以喺瀏覽器直接試寫 TypeScript 程式碼。

Playground 嘅好處:

  • 唔需要安裝任何軟件
  • 即時睇到編譯結果
  • 可以分享程式碼俾其他人
  • 有豐富嘅範例可以學習

你可以喺 TypeScript Playground 試試。

本地開發環境設置

1. 安裝 Node.js 同 npm

bash
1# 檢查是否已安裝
2node --version
3npm --version

2. 安裝 TypeScript

bash
1# 全域安裝
2npm install -g typescript
3
4# 檢查安裝
5tsc --version

3. 創建 TypeScript 專案

bash
1# 創建專案資料夾
2mkdir my-typescript-project
3cd my-typescript-project
4
5# 初始化 npm 專案
6npm init -y
7
8# 創建 TypeScript 配置檔案
9tsc --init

4. 基本專案結構

plaintext
1my-typescript-project/
2├── src/
3│   ├── index.ts
4│   └── utils/
5│       └── helpers.ts
6├── dist/          # 編譯後嘅 JavaScript 檔案
7├── node_modules/
8├── package.json
9└── tsconfig.json  # TypeScript 配置

tsconfig.json 配置

json
1{
2  "compilerOptions": {
3    "target": "ES2020",           // 編譯目標
4    "module": "commonjs",         // 模組系統
5    "outDir": "./dist",           // 輸出目錄
6    "rootDir": "./src",           // 源碼目錄
7    "strict": true,               // 嚴格模式
8    "esModuleInterop": true,      // ES 模組互操作
9    "skipLibCheck": true,         // 跳過庫檔案檢查
10    "forceConsistentCasingInFileNames": true
11  },
12  "include": ["src/**/*"],        // 包含嘅檔案
13  "exclude": ["node_modules", "dist"]
14}

常用編輯器同擴展

Visual Studio Code

  • TypeScript Hero:自動導入管理
  • Prettier:程式碼格式化
  • ESLint:程式碼檢查
  • Auto Rename Tag:自動重命名標籤

WebStorm

  • 內建 TypeScript 支援
  • 智能重構
  • 強大嘅除錯功能

TypeScript 最佳實踐

1. 命名約定

typescript
1// 變數同函式:camelCase
2let userName = "小明";
3function getUserInfo() { }
4
5// 類別同介面:PascalCase
6class UserManager { }
7interface UserData { }
8
9// 常數:UPPER_SNAKE_CASE
10const MAX_RETRY_COUNT = 3;
11
12// 類型別名:PascalCase
13type UserRole = "admin" | "user" | "guest";

2. 使用嚴格模式

typescript
1// 啟用嚴格模式可以捕獲更多錯誤
2// tsconfig.json 中設置 "strict": true
3
4// 避免使用 any
5let data: any = getData(); // ❌ 不好
6let data: UserData = getData(); // ✅ 好
7
8// 處理可能為 null 嘅值
9function processUser(user: User | null) {
10  if (user) {
11    // 安全地使用 user
12    console.log(user.name);
13  }
14}

3. 善用類型守衛(Type Guards)

typescript
1function isString(value: any): value is string {
2  return typeof value === "string";
3}
4
5function processValue(value: string | number) {
6  if (isString(value)) {
7    // TypeScript 知道 value 係 string
8    console.log(value.toUpperCase());
9  } else {
10    // TypeScript 知道 value 係 number
11    console.log(value.toFixed(2));
12  }
13}

4. 使用泛型(Generics)

typescript
1// 創建可重用嘅函式
2function identity<T>(arg: T): T {
3  return arg;
4}
5
6let output1 = identity<string>("myString");
7let output2 = identity<number>(100);
8
9// 泛型介面
10interface ApiResponse<T> {
11  data: T;
12  status: number;
13  message: string;
14}
15
16type UserResponse = ApiResponse<User>;
17type ProductResponse = ApiResponse<Product>;

常見錯誤同解決方法

1. 類型錯誤

typescript
1// 錯誤:Type 'string' is not assignable to type 'number'
2let age: number = "25"; // ❌
3
4// 解決:確保類型匹配
5let age: number = 25; // ✅
6let ageString: string = "25"; // ✅

2. 空值錯誤

typescript
1// 錯誤:Object is possibly 'null'
2function getUser(): User | null { /* ... */ }
3let user = getUser();
4console.log(user.name); // ❌
5
6// 解決:檢查空值
7let user = getUser();
8if (user) {
9  console.log(user.name); // ✅
10}

3. 模組導入錯誤

typescript
1// 錯誤:Cannot find module
2import { helper } from "./helper"; // ❌ 缺少副檔名
3
4// 解決:正確嘅導入路徑
5import { helper } from "./helper.js"; // ✅

🎯 互動練習 6:自由創作

7. 知識檢查

🎯 互動練習 7:知識測驗

重點:

  • TypeScript 係 JavaScript 嘅超集,唔係全新語言
  • 主要優勢係類型檢查,幫助發現錯誤
  • 最終會編譯成普通嘅 JavaScript 程式碼

總結

今日學到嘅重點

  • TypeScript 係 JavaScript 嘅超集:所有 JavaScript 程式碼都係有效嘅 TypeScript 程式碼
  • 類型註解:用 : type 嘅方式指定變數類型
  • 基本類型stringnumberboolean、陣列等
  • 函式類型:可以指定參數同返回值嘅類型
  • 類型安全:TypeScript 可以喺寫程式碼時就發現錯誤

課後建議

  1. TypeScript Playground 試下今日學嘅內容
  2. 試下將一啲簡單嘅 JavaScript 程式碼加上類型註解
  3. 觀察編輯器點樣提供更好嘅提示
  4. 重複做上面嘅互動練習,直到完全理解

下一課預告

下一課我哋會學習:

  • 如何設置 TypeScript 開發環境
  • 編譯 TypeScript 程式碼
  • 基本嘅專案結構
  • 更多實用嘅類型功能

恭喜你完成第一課! 🎉

你已經踏出學習 TypeScript 嘅第一步。記住,學習程式設計最重要係多練習,唔好怕犯錯。每個錯誤都係學習嘅機會!