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函數接收兩個不同的類型T和U,並將它們合併為一個新的對象返回。
總結
- 泛型 將類型作為參數處理,使代碼可重複使用且類型安全。
- 通過在 函數、類別和介面 中使用泛型,您可以編寫處理各類型的靈活邏輯。
- 通過為類型參數添加 約束 或設置 預設類型參數,您可以控制泛型的範圍。
使用泛型,您可以編寫與類型無關的通用代碼,充分利用 TypeScript 強大的類型系統。
您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。