當我們在編寫 TypeScript 程式碼時,經常會遇到需要通用(Generic)的情況,這時候,泛型就是我們的好幫手了。在本篇文章中,我們將深入介紹 TypeScript 泛型的概念以及如何使用。
什麼是泛型?
在程式語言中,泛型指的是引數化型別的概念。也就是說,我們可以定義一個函式、介面或類等,能夠處理不同型別的資料,而不是隻能處理一種型別的資料。這使得我們的程式碼更加靈活、通用、可複用。
下面是一個簡單的泛型函式的例子:
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("hello world");
console.log(output); // 輸出 hello world
上面這個函式用於返回的值與傳入的引數型別相同,這類函式通常稱為 Identity 函式。這裡使用了 <T>
來代表泛型型別,在函式宣告時,我們用具體型別替換了 <T>
,使得函式可以處理任意型別的資料。
泛型類
我們也可以編寫在類中使用泛型的程式碼。下面是一個簡單的例子:
class Queue<T> {
private list: T[] = [];
push(item: T) {
this.list.push(item);
}
pop() {
return this.list.shift();
}
}
let queue = new Queue<string>();
queue.push("first element");
queue.push("second element");
console.log(queue.pop()); // 輸出 first element
console.log(queue.pop()); // 輸出 second element
在這個例子中,我們定義了一個 Queue 類,它使用了泛型型別 T
,表示佇列中元素的型別。我們可以透過呼叫 push()
和 pop()
方法來新增和移除元素。
泛型型別約束
有時候,我們希望泛型所代表的型別必須滿足一定的條件,這個時候我們可以透過新增型別約束來實現。下面是一個簡單例子:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity("hello"); // 輸出 5
在上面的例子中,我們定義了一個泛型函式 loggingIdentity
,它接受一個引數 arg
,該引數的型別必須是一個具有 length
屬性的物件。我們透過 extends
關鍵字來實現型別約束。
在泛型中使用型別別名
在 TypeScript 中,我們還可以使用型別別名來定義泛型型別。下面是一個簡單的例子:
type Coordinate = [number, number];
function distance(a: Coordinate, b: Coordinate): number {
const [x1, y1] = a;
const [x2, y2] = b;
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}
console.log(distance([0, 0], [3, 4])); // 輸出 5
在上面的例子中,我們定義了一個型別別名 Coordinate
,它是一個元組型別,包含兩個數字。然後我們定義了一個 distance
函式,它接受兩個 Coordinate
型別的引數,並計算兩點之間的距離。
總結
在本篇文章中,我們深入介紹了 TypeScript 中泛型的概念,以及提供了一些實際應用的例子。泛型是一個非常強大且常用的特性,它可以使我們的程式碼更加通用、靈活以及可複用。希望透過本篇文章的介紹,你能夠更加深入地理解 TypeScript 中的泛型。