TypeScript 泛型的使用
前言:
在JavaScript
中,封裝一個(gè)API可以具有多種用途,因?yàn)槠鋵?shí)弱類型語言,但是就因?yàn)槭侨躅愋涂梢宰罱K得到的結(jié)果并不是我們想要的。
TypeScript的出現(xiàn)正好中解決了這個(gè)問題,但是考慮到API的復(fù)用時(shí),TypeScript又顯得不是這么的靈活。這個(gè)時(shí)候可以使用any類型來解決不靈活的問題,但是又回到JavaScript中的問題,得到最終的結(jié)果可能不是預(yù)期的那個(gè)樣子。
為了解決這種情況,TypeScript
推出了泛型 的概念,使用泛型可以在定義函數(shù)、接口或類的時(shí)候,不預(yù)先指定具體的類型,而在使用的時(shí)候再指定類型,這樣做的目的是為了更大程度的來復(fù)用我們的代碼。
1.簡(jiǎn)單的使用
現(xiàn)在我們要定義一個(gè)join
函數(shù),該函數(shù)的功能主要是接受兩個(gè)類型一樣的值,返回兩個(gè)參數(shù)拼接后的值。示例代碼如下:
// 所謂的泛型,通俗一點(diǎn)的解釋就是泛指的類型 // 定義一個(gè)join函數(shù),接受兩個(gè)一樣類型的參數(shù),并將兩個(gè)參數(shù)拼接后返回。 function join<T>(first: T, second: T) { return `${first}${second}` } // 這里明確 T 為 string 類型 join<string>('第一', '第二') // 第一第二 // 這里通過類型推導(dǎo)的方式,編譯器會(huì)根據(jù)傳入的參數(shù)自動(dòng)推斷出類型 join(1, 2) // 12
定義泛型是通過<>對(duì)尖括號(hào)來定義,我們?cè)诙xjoin函數(shù)的時(shí)候,并不知道可以接受那些類型,但是可以明確的是兩個(gè)類型是必須一樣的,如果想要滿足這樣的需求,不用泛型的話解決起來是沒有這么簡(jiǎn)單的。
在調(diào)用函數(shù)的時(shí)候,這里使用了兩種方式,一種是直接指定類型為string類型;另一種是通過類型推導(dǎo)的方式,編輯器會(huì)根據(jù)傳入的參數(shù)自動(dòng)幫助我們確定類型。
2.在函數(shù)中使用泛型
在定義一個(gè)函數(shù)時(shí),我們可以使用多個(gè)泛型,而且返回值類型也可以通過泛型指定,只要在數(shù)量上和使用方式上能對(duì)應(yīng)就可以。
示例代碼如下:
function identity<T, Y, P>(first: T, second: Y, third: P): Y { return second } // 指定類型 identity<boolean, string, number>(true, '字符串', 123) // 字符串 // 類型推斷 identity('string', 123, true) // true
3.在類中使用泛型
我們不僅可以在函數(shù)中使用泛型,還可以在類中使用泛型。
示例代碼如下:
class DataManager<T> { // 定義一個(gè)類,該類中具有一個(gè)T類型的私有數(shù)組 constructor(private data: T[]) {} // 根據(jù)索引說數(shù)組中的值 getItem(index: number): T { return this.data[index] } } const data = new DataManager(['一碗周']) data.getItem(0) // 一碗周
而且泛型還可以繼承與于某個(gè)接口,示例代碼如下:
interface Item { name: string } class DataManager<T extends Item> { // 定義一個(gè)類,該類中具有一個(gè)T類型的私有數(shù)組 constructor(private data: T[]) {} // 根據(jù)索引說數(shù)組中的值 getItem(index: number): string { return this.data[index].name } } const data = new DataManager([{ name: '一碗周' }]) data.getItem(0) // 一碗周
使用extends
可以達(dá)到一個(gè)泛型約束 的作用,就上面那個(gè)代碼來說,我們必須約束傳入的值必有具有一個(gè)name屬性,否則就會(huì)拋出異常。
4.在泛型約束中使用類型參數(shù)
假如有如下需求,我們定義一個(gè)類,在類中一個(gè)私有對(duì)象,該對(duì)象中包含一些屬性;然后定義一個(gè)方法,通過key來獲取其對(duì)應(yīng)的值。
實(shí)現(xiàn)代碼如下:
// 定義一個(gè)接口 interface Person { name: string age: number hobby: string } // 定義一個(gè)類 class Me { constructor(private info: Person) {} getInfo(key: string) { return this.info[key] } } const me = new Me({ name: '一碗周', age: 18, hobby: 'coding', }) // 調(diào)用 me.getInfo() 可能會(huì)得到一個(gè) undefined 如下示例 me.getInfo('myName') // undefined
上面的代碼,如果我們調(diào)用示實(shí)例對(duì)象中的getInfo()
方法時(shí),傳入一個(gè)沒有的屬性,會(huì)得到一個(gè)undefined。調(diào)用一個(gè)方法返回一個(gè)undefined
時(shí),這并不是TypeScript
中的作風(fēng)。
解決該問題可以通過keyof操作符,該關(guān)鍵字可以通過該操作符可以用于獲取某種類型的所有鍵,其返回類型是聯(lián)合類型。
示例代碼如下:
type myPerson = keyof Person // 'name' | 'age' | 'hobby'
那現(xiàn)在就可以通過該操作符解決上面出現(xiàn)的那個(gè)問題
示例代碼如下:
class Me { constructor(private info: Person) {} // 該寫法與如下寫法是一樣的 getInfo<T extends keyof Person>(key: T): Person[T] { return this.info[key] } // getInfo<T extends 'name' | 'age' | 'hobby'>(key: T): Person[T] { // return this.info[key] // } } const me = new Me({ name: '一碗周', age: 18, hobby: 'coding', }) // 調(diào)用 me.getInfo() 如果傳遞一個(gè)未知的屬性則會(huì)編譯錯(cuò)誤 me.getInfo('myName') // error : 類型“"myName"”的參數(shù)不能賦給類型“keyof Person”的參數(shù)。
現(xiàn)在我們只要訪問對(duì)象中不具有的屬性編譯則會(huì)異常。
到此這篇關(guān)于TypeScript 泛型的使用的文章就介紹到這了,更多相關(guān)TypeScript 泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章

JS把內(nèi)容動(dòng)態(tài)插入到DIV的實(shí)現(xiàn)方法

JavaScript編程設(shè)計(jì)模式之觀察者模式(Observer Pattern)實(shí)例詳解

JavaScript實(shí)現(xiàn)圖片自動(dòng)加載的瀑布流效果

js+html5實(shí)現(xiàn)半透明遮罩層彈框效果