TypeScript 中的泛型

TypeScript 中的泛型

本文介紹了 TypeScript 中的泛型。

YouTube Video

TypeScript 中的泛型

TypeScript 中的泛型是一種功能,允許您通過參數化類型來定義可重用且類型安全的函數、類和介面。使用泛型可以讓您編寫不依賴於特定類型的程式碼,使您能夠對多種類型執行相同的操作。

泛型的基礎知識

泛型就像接受類型作為參數的模板,允許函數和類處理不同的類型。

泛型函數

以下是一個使用泛型指定其參數類型的函數範例。

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity<number>(42));       // 42
6console.log(identity<string>("Hello"));  // Hello
  • T 是一個泛型類型參數,表示函數參數和返回值的類型。實際類型是在調用函數時確定的。
  • 通過明確指定 <number><string>,您就定義了類型。

即使沒有明確指定泛型類型,TypeScript 也會進行類型推斷。

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity(42));       // 42
6console.log(identity("Hello"));  // Hello
  • 即使沒有明確指定 <number><string>,也會進行型別推論。identity(42) 被推論為 number,而 identity("Hello") 被推論為 string

泛型的限制

通過對泛型設置限制,您可以將其限制為僅接受特定類型。

1function loggingIdentity<T extends { length: number }>(arg: T): T {
2    console.log(arg.length);
3    return arg;
4}
5
6loggingIdentity("Hello");  // 5
7loggingIdentity([1, 2, 3]);  // 3
8
9// loggingIdentity(42);  // Error: number does not have a length property.
  • 指定 T extends { length: number } 表示 T 必須是一個具有 length 屬性的類型。因此,不具有 length 屬性的類型將無法被接受。

keyof 的結合

將泛型與 keyof 結合,可以以型別安全的方式取得屬性名稱。

1function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
2  return obj[key];
3}
4
5const person = { name: "Bob", age: 30 };
6const personName = getProperty(person, "name"); // string
7console.log(personName);
8
9// const error = getProperty(person, "unknown"); // Error
  • K 受到 keyof T 限制,表示只能指定存在於 T 中的鍵。指定不存在的鍵會導致編譯錯誤。

泛型類

類也可以使用泛型來定義。泛型類為屬性和方法提供了靈活的類型。

 1class Box<T> {
 2    private _value: T;
 3
 4    constructor(value: T) {
 5        this._value = value;
 6    }
 7
 8    public getValue(): T {
 9        return this._value;
10    }
11
12    public setValue(value: T): void {
13        this._value = value;
14    }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue());  // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue());  // Hello
  • Box<T> 將類中的類型 T 宣告為泛型。這使得同一個類可以重複用於不同的類型。

泛型介面

泛型也可以與介面一起使用。

 1interface Pair<T, U> {
 2    first: T;
 3    second: U;
 4}
 5
 6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
 7console.log(numberStringPair);  // { first: 1, second: 'One' }
 8
 9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair);  // { first: true, second: [ 1, 2, 3 ] }
  • 通過使用 Pair<T, U> 指定兩個泛型類型,您可以定義一個具有不同類型組合的物件。

預設類型參數

也可以為泛型參數指定一個預設的類型。

1function createArray<T = string>(length: number, value: T): T[] {
2    return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a"));   // ['a', 'a', 'a']
6console.log(createArray(3, 100));   // [100, 100, 100]
  • 我們使用 <T = string> 將預設類型參數設置為 string。如果沒有顯式指定類型,T 的類型將為 string

泛型類型別名

泛型也可以用作類型別名(type)。

 1type Result<T> = {
 2    success: boolean;
 3    data: T;
 4};
 5
 6const successResult: Result<number> = { success: true, data: 42 };
 7const errorResult: Result<string> = { success: false, data: "Error occurred" };
 8
 9console.log(successResult);  // { success: true, data: 42 }
10console.log(errorResult);    // { success: false, data: 'Error occurred' }
  • Result<T> 代表一個包含 T 類型數據的結果對象。通過這種方式,您可以使用泛型創建靈活的類型別名。

多個泛型類型

通過使用多個泛型類型,您可以定義更具多樣性的函數和類別。

1function merge<T, U>(obj1: T, obj2: U): T & U {
2    return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged);  // { name: 'Alice', title: 'Engineer' }
  • merge 函數接收兩個不同的類型 TU,並將它們合併為一個新的對象返回。

總結

  • 泛型 將類型作為參數處理,使代碼可重複使用且類型安全。
  • 通過在 函數、類別和介面 中使用泛型,您可以編寫處理各類型的靈活邏輯。
  • 通過為類型參數添加 約束 或設置 預設類型參數,您可以控制泛型的範圍。

使用泛型,您可以編寫與類型無關的通用代碼,充分利用 TypeScript 強大的類型系統。

您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。

YouTube Video