新聞中心
本文轉(zhuǎn)載自微信公眾號(hào)「JS每日一題」,作者灰灰。轉(zhuǎn)載本文請(qǐng)聯(lián)系JS每日一題公眾號(hào)。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)愛民免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上千多家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
一、是什么
泛型程序設(shè)計(jì)(generic programming)是程序設(shè)計(jì)語言的一種風(fēng)格或范式
泛型允許我們?cè)趶?qiáng)類型程序設(shè)計(jì)語言中編寫代碼時(shí)使用一些以后才指定的類型,在實(shí)例化時(shí)作為參數(shù)指明這些類型 在typescript中,定義函數(shù),接口或者類的時(shí)候,不預(yù)先定義好具體的類型,而在使用的時(shí)候在指定類型的一種特性
假設(shè)我們用一個(gè)函數(shù),它可接受一個(gè) number 參數(shù)并返回一個(gè)number 參數(shù),如下寫法:
- function returnItem (para: number): number {
- return para
- }
如果我們打算接受一個(gè) string 類型,然后再返回 string類型,則如下寫法:
- function returnItem (para: string): string {
- return para
- }
上述兩種編寫方式,存在一個(gè)最明顯的問題在于,代碼重復(fù)度比較高
雖然可以使用 any類型去替代,但這也并不是很好的方案,因?yàn)槲覀兊哪康氖墙邮帐裁搭愋偷膮?shù)返回什么類型的參數(shù),即在運(yùn)行時(shí)傳入?yún)?shù)我們才能確定類型
這種情況就可以使用泛型,如下所示:
- function returnItem
(para: T): T { - return para
- }
可以看到,泛型給予開發(fā)者創(chuàng)造靈活、可重用代碼的能力
二、使用方式
泛型通過<>的形式進(jìn)行表述,可以聲明:
- 函數(shù)
- 接口
- 類
函數(shù)聲明
聲明函數(shù)的形式如下:
- function returnItem
(para: T): T { - return para
- }
定義泛型的時(shí)候,可以一次定義「多個(gè)類型參數(shù)」,比如我們可以同時(shí)定義泛型 T 和 泛型 U:
- function swap
(tuple: [T, U]): [U, T] { - return [tuple[1], tuple[0]];
- }
- swap([7, 'seven']); // ['seven', 7]
接口聲明
聲明接口的形式如下:
- interface ReturnItemFn
{ - (para: T): T
- }
那么當(dāng)我們想傳入一個(gè)number作為參數(shù)的時(shí)候,就可以這樣聲明函數(shù):
- const returnItem: ReturnItemFn
= para => para
類聲明
使用泛型聲明類的時(shí)候,既可以作用于類本身,也可以作用于類的成員函數(shù)
下面簡(jiǎn)單實(shí)現(xiàn)一個(gè)元素同類型的棧結(jié)構(gòu),如下所示:
- class Stack
{ - private arr: T[] = []
- public push(item: T) {
- this.arr.push(item)
- }
- public pop() {
- this.arr.pop()
- }
- }
使用方式如下:
- const stack = new Stacn()
如果上述只能傳遞 string 和 number 類型,這時(shí)候就可以使用 的方式猜實(shí)現(xiàn)「約束泛型」,如下所示:
除了上述的形式,泛型更高級(jí)的使用如下:
例如要設(shè)計(jì)一個(gè)函數(shù),這個(gè)函數(shù)接受兩個(gè)參數(shù),一個(gè)參數(shù)為對(duì)象,另一個(gè)參數(shù)為對(duì)象上的屬性,我們通過這兩個(gè)參數(shù)返回這個(gè)屬性的值
這時(shí)候就設(shè)計(jì)到泛型的索引類型和約束類型共同實(shí)現(xiàn)
索引類型、約束類型
索引類型 keyof T 把傳入的對(duì)象的屬性類型取出生成一個(gè)聯(lián)合類型,這里的泛型 U 被約束在這個(gè)聯(lián)合類型中,如下所示:
- function getValue
(obj: T, key: U) { - return obj[key] // ok
- }
上述為什么需要使用泛型約束,而不是直接定義第一個(gè)參數(shù)為 object類型,是因?yàn)槟J(rèn)情況 object 指的是{},而我們接收的對(duì)象是各種各樣的,一個(gè)泛型來表示傳入的對(duì)象類型,比如 T extends object
使用如下圖所示:
多類型約束
例如如下需要實(shí)現(xiàn)兩個(gè)接口的類型約束:
- interface FirstInterface {
- doSomething(): number
- }
- interface SecondInterface {
- doSomethingElse(): string
- }
可以創(chuàng)建一個(gè)接口繼承上述兩個(gè)接口,如下:
- interface ChildInterface extends FirstInterface, SecondInterface {
- }
正確使用如下:
- class Demo
{ - private genericProperty: T
- constructor(genericProperty: T) {
- this.genericProperty = genericProperty
- }
- useT() {
- this.genericProperty.doSomething()
- this.genericProperty.doSomethingElse()
- }
- }
通過泛型約束就可以達(dá)到多類型約束的目的
三、應(yīng)用場(chǎng)景
通過上面初步的了解,后述在編寫 typescript 的時(shí)候,定義函數(shù),接口或者類的時(shí)候,不預(yù)先定義好具體的類型,而在使用的時(shí)候在指定類型的一種特性的時(shí)候,這種情況下就可以使用泛型
靈活的使用泛型定義類型,是掌握typescript 必經(jīng)之路
參考文獻(xiàn)
https://www.tslang.cn/docs/handbook/generics.html
網(wǎng)站題目:面試官:說說你對(duì) TypeScript 中泛型的理解?應(yīng)用場(chǎng)景?
本文網(wǎng)址:http://m.5511xx.com/article/dphedsg.html


咨詢
建站咨詢
