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