TypeScript 裡的泛型(Generics)允許我們在定義函式、類別或介面時不必指定具體的資料型別,而是使用佔位符<>
,讓這些結構可以運作於不同的資料型別上。這樣的設計能夠提高程式的重用性和靈活性,並在編譯時提供更好的型別檢查。
在 TypeScript 中,使用泛型的基本語法是將型別參數放在尖括號(<>
)中。型別參數可以是任何有效的識別符,通常會使用單個字母,例如 T
、U
或 K
等。
function toArrayByParam<T>(param: T): T[] {
return [param];
}
泛型(Generics)不僅可以用於函式,還可以在類別和介面中使用,這使得程式碼更具靈活性和可重用性。以下分別介紹如何應用在各種型別上:
泛型函式是泛型中最常見的使用場景。它允許我們在定義函式時不指定具體的型別,這樣可以讓函式接受不同型別的參數,並返回相應型別的結果。來看看簡單的範例:
function someContent<T>(arg: T): T {
return arg;
}
// 使用範例
const num = someContent<number>(18); // num 的型別是 number
const str = someContent<string>("hello"); // str 的型別是 string
在這個範例中,someContent
函式使用了型別參數 T
,無論傳入何種型別,都能返回相同型別的值。
泛型類別也可以讓我們定義一個類別,而該類別的屬性和方法可以接受多種型別,在實例化時可以確定具體型別。以下是一個堆疊類別的例子:
class GenericStack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
isEmpty(): boolean {
return this.items.length === 0;
}
}
// 使用範例
const stack = new GenericStack<number>();
stack.push(1);
stack.push(2);
console.log(stack.pop()); // 2
在這裡,GenericStack
類別可以存儲任意型別的資料,根據需要使用不同的型別實例化它。
泛型介面定義了具有泛型屬性的型別,這使得介面的使用更加靈活。下面是一個簡單的泛型介面範例:
interface Pair<K, V> {
key: K;
value: V;
}
const numberStringPair: Pair<number, string> = {
key: 1,
value: "One",
};
const stringBooleanPair: Pair<string, boolean> = {
key: "isActive",
value: true,
};
在這個範例裡,Pair
介面有兩個型別參數 K
和 V
,這使得我們可以靈活定義 key 和 value 的型別。
在前一篇文章中學到的型別別名(type
)也可以用在定義泛型的型別。
type Input<T> = {
value: T;
};
const numberInput: Input<number> = {
value: 18,
};
const stringInput: Input<string> = {
value: 'I am Annie.',
};
const numValue: number = numberInput.value;
console.log(numValue); // 18
const stringValue: string = stringInput.value;
console.log(stringValue); // I am Annie.
泛型在函式、類別和介面中的使用,讓我們能夠創建靈活且可重用的程式碼。這不僅提高了型別安全性,還減少了冗餘代碼的產生。透過正確使用泛型,可以大幅提升 TypeScript 應用的可維護性和擴展性。這對於開發大型應用尤為重要,因為它能幫助開發者避免常見的型別錯誤,並在編譯時進行檢查。