TypeScript 為什么要引入泛型?
泛型(Generics)是 Typescript 中很重要的一個特性,它可以幫助我們創(chuàng)建可重用的組件,同時還能具備類型安全性。
主要的優(yōu)點有:
- 更好的可重用性:通過泛型可以創(chuàng)建一個組件,使其可以支持多種類型,比如創(chuàng)建一個函數(shù)或類時,不預(yù)先指定具體的類型,而是在使用的時候再指定類型。這樣就可以對不同的類型重復(fù)使用同一個組件。
- 類型安全:泛型會要求在使用組件時傳入的類型與組件內(nèi)部使用的類型一致,可以在編譯時發(fā)現(xiàn)錯誤。
- 靈活性:可以只在需要的時候指定類型參數(shù),并且參數(shù)可以有多個。類型參數(shù)也可以限制約束條件來約束傳入的類型。
- 對于接口和類來說,泛型可以明確成員的類型,增強代碼的可讀性。
常見的泛型用法有:
- 泛型函數(shù)和泛型類:可以定義泛型函數(shù)或泛型類,在實例化時指定類型參數(shù)
- 泛型接口:可以定義泛型接口,使接口更靈活適用
- 泛型約束:可以對泛型的類型參數(shù)加以約束
總之,泛型是 Typescript 強大的類型系統(tǒng)特性之一,可以構(gòu)建靈活、可重用且類型安全的組件,提高代碼質(zhì)量和可維護性。正確使用泛型能大大提升 Typescript 的開發(fā)體驗。
泛型是什么?
?泛型程序設(shè)計(generic programming)
?是程序設(shè)計語言的一種風(fēng)格或范式
泛型允許我們在強類型程序設(shè)計語言中編寫代碼時使用一些以后才指定的類型,在實例化時作為參數(shù)指明這些類型 在typescript中,定義函數(shù),接口或者類的時候,不預(yù)先定義好具體的類型,而在使用的時候在指定類型的一種特性
假設(shè)我們用一個函數(shù),它可接受一個 number 參數(shù)并返回一個number 參數(shù),如下寫法:
function returnItem (para: number): number {
return para
}
如果我們打算接受一個 string 類型,然后再返回 string類型,則如下寫法:
function returnItem (para: string): string {
return para
}
上述兩種編寫方式,存在一個最明顯的問題在于,代碼重復(fù)度比較高
雖然可以使用 any類型去替代,但這也并不是很好的方案,因為我們的目的是接收什么類型的參數(shù)返回什么類型的參數(shù),即在運行時傳入?yún)?shù)我們才能確定類型
這種情況就可以使用泛型,如下所示:
function returnItem<T>(para: T): T {
return para
}
可以看到,泛型給予開發(fā)者創(chuàng)造靈活、可重用代碼的能力。
泛型的使用方式
泛型的使用方式主要有以下幾種:
1. 泛型函數(shù)
可以在函數(shù)名稱后添加尖括號來定義泛型函數(shù),在函數(shù)體中使用 T 來表示泛型類型。調(diào)用時指定類型參數(shù):
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("myString");
2. 泛型接口
可以在接口名稱后添加尖括號來定義泛型接口,接口中的屬性則可以使用 T 來表示類型:
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
// ...
}
let myIdentity: GenericIdentityFn<number> = identity;
3. 泛型類
可以在類名稱后添加尖括號來定義泛型類,類中的屬性或方法則可以使用 T 來表示類型:
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
4. 泛型約束
可以通過 extends 關(guān)鍵字添加約束條件:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
這些是泛型的常見用法,可以靈活運用泛型來實現(xiàn)組件的可重用性和類型安全。泛型的使用方式
泛型的應(yīng)用場景
泛型的常見應(yīng)用場景包括:
1. 封裝組件
可以使用泛型來封裝可重用的組件,比如創(chuàng)建一個通用的緩存組件:
class Cache<T> {
private data: T;
constructor(data: T) {
this.data = data;
}
get() {
return this.data;
}
set(data: T) {
this.data = data;
}
}
const numCache = new Cache<number>(123);
這樣這個緩存組件就可以支持不同的類型。
2. 函數(shù)重載
可以使用泛型給函數(shù)增加多種類型的重載定義:
function arrayOf<T>(value: T): T[];
function arrayOf<T>(value: T[]): T[];
function arrayOf<T>(value: T | T[]): T[] {
return Array.isArray(value) ? value : [value];
}
3. 接口定義
可以使用泛型給接口增加靈活性:
interface Result<T> {
data: T;
error?: string;
}
const result: Result<number> = {
data: 123
};
4. 類型別名
可以給類型別名增加泛型:
type PromiseResponse<T> = Promise<{
data: T;
error?: string;
}>
5. 泛型約束
可以對泛型加以約束,限制泛型的類型范圍。
綜上,泛型的應(yīng)用場景非常廣泛,合理利用泛型可以大幅提高代碼的靈活性和復(fù)用性。