typeScript?泛型使用和泛型接口結(jié)合
typeScript 中新增的泛型概念、泛型使用、泛型與接口結(jié)合:
在實(shí)際應(yīng)用中可能會(huì)遇到求最小值的問(wèn)題,比如求數(shù)組中的最小值。
在 ts
中的就需要寫兩種方式,一種針對(duì) number
,另外一種針對(duì)字符串。
這樣寫不利于代碼重用,項(xiàng)目較大時(shí),性能較差,同時(shí)工作效率也低,所以在 ts 中引入了泛型概念。
function getMin1(arr:number[]):number { ?let min = arr[0] ?for (var i = 1; i < arr.length; i++){ ? if (min > arr[i]) { ? ?min = arr[i] ? } ?} ?return min } console.log(getMin1([1, 2, 3, 4])); function getMin2(arr:string[]):string { ?let min = arr[0] ?for (var i = 1; i < arr.length; i++){ ? if (min > arr[i]) { ? ?min = arr[i] ? } ?} ?return min } console.log(getMin2(['a', 'b', 'c']));
1、泛型是啥?
泛型英文是 generics
,是指在定義函數(shù)、接口或類的時(shí)候,不預(yù)先指定具體的類型,而是在使用的時(shí)候再指定類型的一種。
定義方式:
function fnName<T>(arg:T,...):T{ ?return ... }
泛型變量通常用 T 來(lái)表示,T可以表示任何類型。
所以呢,我們可以將上述實(shí)例修改成以下代碼:
function getMin<T>(arr: T[]): T{ ?let min = arr[0] ?for (var i = 1; i < arr.length; i++){ ? if (min > arr[i]) { ? ?min = arr[i] ? } ?} ?return min } getMin<number>([1, 2, 3, 4]) getMin<string>(['a', 'b', 'c', 'd'])
上述代碼中,T 的主要作用就是幫助我們來(lái)捕獲用戶傳入的類型,比如 :number
或 string
。另外編譯器也會(huì)根據(jù)傳入的參數(shù)自動(dòng)地幫助我們進(jìn)行類型推斷,然后把 T 設(shè)置為它的類型,所以可以忽略類型的傳入,如:
getMin([1, 2, 3, 4]) getMin(['a', 'b', 'c', 'd'])
在一些復(fù)雜的情況下,為了防止編譯器自動(dòng)推斷類似失敗,盡可能地將類型傳入,防止出錯(cuò)。
2、泛型類型
泛型函數(shù)的類型和非泛型函數(shù)的類型有什么不同?
它們看著很相似,泛型函數(shù)類型前面有一個(gè)類型參數(shù) <T>。
對(duì)于泛型函數(shù)類型還有以下特性:
a>、泛型函數(shù)類型可以有多個(gè)參數(shù)
function fn<T, U>(arg1: T, arg2: U) { ?return arg1 }
b>、泛型函數(shù)可以使用不同的泛型參數(shù)名
function fn<T>(arg1: T) { ?return arg1 } let Fn: <M>(arg1: M) => M = fn
c>、可以使用帶有對(duì)象字面量的方式定義泛型函數(shù)
function fn<T>(arg1: T) { ?return arg1 } let Fn: {<T>(arg: T): T} = fn
3、泛型接口
在使用對(duì)象字面量的方式定義泛型函數(shù)時(shí),對(duì)象的形式可以替換成接口的形式,改為:
let Fn: { <T>(arg: T): T } = fn //替換為 interface FnInter{ ?<T>(arg: T): T } let Fn: FnInter = fn
這種方式存在問(wèn)題:函數(shù)對(duì)數(shù)據(jù)類型一無(wú)所知,無(wú)法使用某個(gè)數(shù)據(jù)類型進(jìn)行操作。所以需要改良下,將類型作為參數(shù)傳入,如:
interface FnInter<T>{ ?(arg:T): T } let Fn: FnInter<string> = fn
這樣我們就能清楚地知道使用的具體是那個(gè)泛型類型。
我們將整個(gè)接口當(dāng)做泛型參數(shù),就叫做泛型接口。它的優(yōu)點(diǎn)就是我們能清除知道參數(shù)的數(shù)據(jù)類型,接口內(nèi)的成員也能知道參數(shù)的具體類型。
4、泛型類
除了有泛型接口之外,還有接口類。泛型類與泛型函數(shù)差不多。
語(yǔ)法格式為:
class 名稱<T>{} new 類名<類型>()
class GetMin<T>{ ? arr: T[] = [] ? add(ele:T) { ?this.arr.push(ele) ? } ? getMin(): T{ ?var min = this.arr[0] ?for (var i = 0; i < this.arr.length; i++){ ? if (min > this.arr[i]) { ? ?min = this.arr[i] ? } ?} ?return min ?} } let gMin1 = new GetMin<number>() gMin1.add(1) gMin1.add(5) console.log(gMin1.getMin());//1 let gMin2 = new GetMin<string>() gMin2.add('a') gMin2.add('b') console.log(gMin2.getMin());//2
5、泛型約束
泛型功能確實(shí)挺強(qiáng)大的,但它也不是萬(wàn)能的。比如:
function getLength<T>(val: T): number { ?return val.length; }
錯(cuò)誤信息提示:類型“T”上不存在屬性“length”。
原因是只有字符串、數(shù)組才有 length 屬性,對(duì)于數(shù)字、對(duì)象沒(méi)有 length 屬性,所以報(bào)錯(cuò)了。解決辦法是要保證傳入的數(shù)據(jù)類型有 length 屬性,所以需要使用泛型約束。
泛型約束主要是通過(guò)接口 + extends
關(guān)鍵字來(lái)實(shí)現(xiàn)約束。
interface ILen{ ?length:number } function getLength<T extends ILen>(val: T): number { ?return val.length; } console.log(getLength<string>("abcd")); console.log(getLength<number>(1)); //錯(cuò)誤提示:類型“number”不滿足約束“ILen”。
使用泛型約束的優(yōu)點(diǎn)是幫我們自動(dòng)檢測(cè)傳入的值是否符合約束類型的值,不滿足時(shí)就會(huì)有錯(cuò)誤提示。
6、泛型參數(shù)默認(rèn)類型
在 typeScript 2.3 以后,可以為泛型中的類型參數(shù)指定默認(rèn)類型,當(dāng)使用泛型時(shí)沒(méi)有指定參數(shù)類型,并且編輯器從實(shí)際參數(shù)中也無(wú)法推斷出數(shù)據(jù)類型時(shí),就使用默認(rèn)類型。
使用簡(jiǎn)單:
interface P<T = string>{ ?name:T } let p1: P = { name: "小姐姐" } let p2: P<number> = { name: 18 }
?泛型參數(shù)的默認(rèn)類型遵循以下規(guī)則:?
- 有默認(rèn)類型的類型參數(shù)被認(rèn)為是可選的。
- 必選的類型參數(shù)不能在可選的類型參數(shù)后。
- 如果類型參數(shù)有約束,類型參數(shù)的默認(rèn)類型必須滿足這個(gè)約束。
- 當(dāng)指定類型實(shí)參時(shí),你只需要指定必選類型參數(shù)的類型實(shí)參。 未指定的類型參數(shù)會(huì)被解析為它們的默認(rèn)類型。
- 如果指定了默認(rèn)類型,且類型推斷無(wú)法選擇一個(gè)候選類型,那么將使用默認(rèn)類型作為推斷結(jié)果。
- 一個(gè)被現(xiàn)有類或接口合并的類或者接口的聲明可以為現(xiàn)有類型參數(shù)引入默認(rèn)類型。
- 一個(gè)被現(xiàn)有類或接口合并的類或者接口的聲明可以引入新的類型參數(shù),只要它指定了默認(rèn)類型。
7、泛型條件類型
在 typeScript 2.8 中,引入了條件類型,我們可以根據(jù)某些條件得到不同的類型,此處的條件是類型兼容性約束。ript 2.8 中,引入了條件類型,我們可以根據(jù)某些條件得到不同的類型,此處的條件是類型兼容性約束。
條件類型會(huì)以一定條件表達(dá)式進(jìn)行類型關(guān)系檢測(cè),從而在兩種類型中選擇其一:
使用語(yǔ)法:
T extends U ? X : Y
?以上表達(dá)式的意思是:若 ?T? 能夠賦值給 ?U?,那么類型是 ?X?,否則為 ?Y?。
到此這篇關(guān)于typeScript
泛型使用和泛型接口結(jié)合的文章就介紹到這了,更多相關(guān)typeScript 泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript單例模式能不能去實(shí)例只留單原理解析
這篇文章主要為大家介紹了JavaScript單例模式能不能去實(shí)例只留單原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12umi插件開發(fā)仿dumi項(xiàng)目實(shí)現(xiàn)頁(yè)面布局詳解
這篇文章主要為大家介紹了umi插件開發(fā)仿dumi項(xiàng)目實(shí)現(xiàn)頁(yè)面布局詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01微信小程序 數(shù)據(jù)綁定及運(yùn)算的簡(jiǎn)單實(shí)例
這篇文章主要介紹了微信小程序 數(shù)據(jù)綁定的簡(jiǎn)單實(shí)例的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09微信小程序 es6-promise.js封裝請(qǐng)求與處理異步進(jìn)程
這篇文章主要介紹了微信小程序 es6-promise.js封裝請(qǐng)求與處理異步進(jìn)程的相關(guān)資料,需要的朋友可以參考下2017-06-06