在之前的基礎型別和小專案上,會發現有時候我們想要在設計專案的時候,有時候會不知道怎麼去預測我需要放置的型別對吧,因此在使用 TypeScript 希望能假裝一下的型別,但又不失去本質的嚴密和正確性,聽起來有點困難吧。但 TypeScript 很貼心的提供了一種用法-泛型( Generics ),就可以在提供最大彈性的同時確保程式碼的嚴謹與正確性。
簡單來說就是可以在宣告的時候,透過 <T>
來強佔一個型別的參數,然後能讓接收到什麼,後續就會當作什麼來使用。聽起來有點抽象對吧,這時候我先上個範例。
let numberArray: Array<number> = [1, 2, 3];
let stringArray: Array<string> = ["a", "b", "c"];
這是一個很直覺的宣告陣列,讓陣列裡面的元素都是同一種型別,但是型別那麼多種,如果要一種宣告一次也太累了吧?這時候就可以用上泛型,但是沒辦法直接像是這樣使用。
let typeArray: Array<T> = []; // 這樣是錯誤的唷,除非自己特別定義過。
之前提到的 T
是一個泛型參數,通常在函式或類別的宣告中使用。如果只是想在一段獨立的程式碼中使用這樣的結構,那麼 T
的會是未定義的。T
可以應用在,例如建立一個函式,而這個函式專門在製作陣列。
function createArray<T>(value: T, length: number): T[] {
let arr: T[] = [];
for (let i = 0; i < length; i++) {
arr.push(value);
}
return arr;
}
let numberArray = createArray<number>(10, 5); // [10, 10, 10, 10, 10]
let stringArray = createArray<string>("test", 3); // ["test", "test", "test"]
在這個例子中,createArray
是一個泛型函數,它接受一個泛型參數 T
。在函數內部,我們使用這個 T
來宣告陣列 arr
,最後返回這個型態的陣列。希望這個例子能幫助大家更好地理解 TypeScript 的泛型宣告方式。
除了基本的函式應用,其他像是 interface 和 class 也是能應用上的,例如。
function peopleAge<T>(arg: Array<T>): Array<T> {
console.log(arg.length);
return arg;
}
interface PeopleAge<T> {
(arg: T): T;
}
class PeopleAge<T> {
add: (x: T, y: T) => T;
}
當然除了上述的功能還有一個特別的功能,就是限制使用。什麼意思呢?請看範例
interface Limit {
length: number;
}
function loggingIdentity<T extends Limit>(arg: T): T {
console.log(arg.length);
return arg;
}
在這個範例上我們用**<T extends Limit>
** 說明了泛型 T 必須符合 **Limit**
的形狀,換句話說就是它必須有 .length
屬性。
TypeScript 的泛型是一個強大的功能,今天我們只介紹了其中的基本用法,而這些基本用法已經提供了更高的程式靈活性和型別的安全性。透過泛型,我們可以寫出更簡潔、重複使用和容易維護的程式碼。希望透過這篇文章,能簡單的讓你對 TypeScript 的泛型有一個基本的了解。