最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

技術(shù)分享!TypeScript學(xué)習(xí)筆記(八)- 泛型

2021-01-06 14:21 作者:光耀三十洲  | 我要投稿

泛型

泛型(Generics)是指在定義函數(shù)、接口或類(lèi)的時(shí)候,不預(yù)先指定具體的類(lèi)型,而在使用的時(shí)候再指定類(lèi)型的一種特性。

我們來(lái)實(shí)現(xiàn)一個(gè)函數(shù) createArray,它可以創(chuàng)建一個(gè)指定長(zhǎng)度的數(shù)組,同時(shí)將每一項(xiàng)都填充一個(gè)默認(rèn)值:

function createArray(length: number, value: any): Array<any> {

? ? let result = [];

? ? for (let i = 0; i < length; i++) {

? ? ? ? result[i] = value;

? ? }

? ? return result;

}


createArray(3, 'x'); // ['x', 'x', 'x']

復(fù)制代碼

我們使用了之前提到過(guò)的數(shù)組泛型來(lái)定義返回值的類(lèi)型。

這段代碼編譯不會(huì)報(bào)錯(cuò),但是一個(gè)顯而易見(jiàn)的缺陷是,它并沒(méi)有準(zhǔn)確的定義返回值的類(lèi)型:

Array 允許數(shù)組的每一項(xiàng)都為任意類(lèi)型。但是我們預(yù)期的是,數(shù)組中每一項(xiàng)都應(yīng)該是輸入的 value 的類(lèi)型。

function createArray<T>(length: number, value: T): Array<T> {

? ? let result: T[] = [];

? ? for (let i = 0; i < length; i++) {

? ? ? ? result[i] = value;

? ? }

? ? return result;

}


createArray<string>(3, 'x'); // ['x', 'x', 'x']

復(fù)制代碼

我們?cè)诤瘮?shù)名后添加了 ,其中 T 用來(lái)指代任意輸入的類(lèi)型,在后面的輸入 value: T 和輸出 Array 中即可使用了。

接著在調(diào)用的時(shí)候,可以指定它具體的類(lèi)型為 string。當(dāng)然,也可以不手動(dòng)指定,而讓類(lèi)型推論自動(dòng)推算出來(lái):

function createArray<T>(length: number, value: T): Array<T> {

? ? let result: T[] = [];

? ? for (let i = 0; i < length; i++) {

? ? ? ? result[i] = value;

? ? }

? ? return result;

}


createArray(3, 'x'); // ['x', 'x', 'x']

復(fù)制代碼

多個(gè)類(lèi)型參數(shù)

定義泛型的時(shí)候,可以一次定義多個(gè)類(lèi)型參數(shù):

function swap<T, U>(tuple: [T, U]): [U, T] {

? ? return [tuple[1], tuple[0]];

}


swap([7, 'seven']); // ['seven', 7]

復(fù)制代碼

上例中,我們定義了一個(gè) swap 函數(shù),用來(lái)交換輸入的元組。

泛型約束

在函數(shù)內(nèi)部使用泛型變量的時(shí)候,由于事先不知道它是哪種類(lèi)型,所以不能隨意的操作它的屬性或方法:

function loggingIdentity<T>(arg: T): T {

? ? console.log(arg.length);

? ? return arg;

}


// index.ts(2,19): error TS2339: Property 'length' does not exist on type 'T'.

復(fù)制代碼

上例中,泛型 T 不一定包含屬性 length,所以編譯的時(shí)候報(bào)錯(cuò)了。

這時(shí),我們可以對(duì)泛型進(jìn)行約束,只允許這個(gè)函數(shù)傳入那些包含 length 屬性的變量。這就是泛型約束:

interface Lengthwise {

? ? length: number;

}


function loggingIdentity<T extends Lengthwise>(arg: T): T {

? ? console.log(arg.length);

? ? return arg;

}

復(fù)制代碼

上例中,我們使用了 extends 約束了泛型 T 必須符合接口 Lengthwise 的形狀,也就是必須包含 length 屬性。

此時(shí)如果調(diào)用 loggingIdentity 的時(shí)候,傳入的 arg 不包含 length,那么在編譯階段就會(huì)報(bào)錯(cuò)了:

interface Lengthwise {

? ? length: number;

}


function loggingIdentity<T extends Lengthwise>(arg: T): T {

? ? console.log(arg.length);

? ? return arg;

}


loggingIdentity(7);


// index.ts(10,17): error TS2345: Argument of type '7' is not assignable to parameter of type 'Lengthwise'.

復(fù)制代碼

多個(gè)類(lèi)型參數(shù)之間也可以互相約束:

function copyFields<T extends U, U>(target: T, source: U): T {

? ? for (let id in source) {

? ? ? ? target[id] = (<T>source)[id];

? ? }

? ? return target;

}


let x = { a: 1, b: 2, c: 3, d: 4 };


copyFields(x, { b: 10, d: 20 });

復(fù)制代碼

上例中,我們使用了兩個(gè)類(lèi)型參數(shù),其中要求 T 繼承 U,這樣就保證了 U 上不會(huì)出現(xiàn) T 中不存在的字段。

泛型接口

之前學(xué)習(xí)過(guò),可以使用接口的方式來(lái)定義一個(gè)函數(shù)需要符合的形狀:

interface SearchFunc {

? (source: string, subString: string): boolean;

}


let mySearch: SearchFunc;

mySearch = function(source: string, subString: string) {

? ? return source.search(subString) !== -1;

}

復(fù)制代碼

當(dāng)然也可以使用含有泛型的接口來(lái)定義函數(shù)的形狀:

interface CreateArrayFunc {

? ? <T>(length: number, value: T): Array<T>;

}


let createArray: CreateArrayFunc;

createArray = function<T>(length: number, value: T): Array<T> {

? ? let result: T[] = [];

? ? for (let i = 0; i < length; i++) {

? ? ? ? result[i] = value;

? ? }

? ? return result;

}


createArray(3, 'x'); // ['x', 'x', 'x']

復(fù)制代碼

進(jìn)一步,我們可以把泛型參數(shù)提前到接口名上:

interface CreateArrayFunc<T> {

? ? (length: number, value: T): Array<T>;

}


let createArray: CreateArrayFunc<any>;

createArray = function<T>(length: number, value: T): Array<T> {

? ? let result: T[] = [];

? ? for (let i = 0; i < length; i++) {

? ? ? ? result[i] = value;

? ? }

? ? return result;

}


createArray(3, 'x'); // ['x', 'x', 'x']

復(fù)制代碼

注意,此時(shí)在使用泛型接口的時(shí)候,需要定義泛型的類(lèi)型。

泛型類(lèi)

與泛型接口類(lèi)似,泛型也可以用于類(lèi)的類(lèi)型定義中:

class GenericNumber<T> {

? ? zeroValue: T;

? ? add: (x: T, y: T) => T;

}


let myGenericNumber = new GenericNumber<number>();

myGenericNumber.zeroValue = 0;

myGenericNumber.add = function(x, y) { return x + y; };

復(fù)制代碼

泛型參數(shù)的默認(rèn)類(lèi)型

在 TypeScript 2.3 以后,我們可以為泛型中的類(lèi)型參數(shù)指定默認(rèn)類(lèi)型。當(dāng)使用泛型時(shí)沒(méi)有在代碼中直接指定類(lèi)型參數(shù),從實(shí)際值參數(shù)中也無(wú)法推測(cè)出時(shí),這個(gè)默認(rèn)類(lèi)型就會(huì)起作用。

function createArray<T = string>(length: number, value: T): Array<T> {

? ? let result: T[] = [];

? ? for (let i = 0; i < length; i++) {

? ? ? ? result[i] = value;

? ? }

? ? return result;

}


作者:轉(zhuǎn)眼歲歲又年年

鏈接:https://juejin.cn/post/6913530341202329607

來(lái)源:掘金

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。


技術(shù)分享!TypeScript學(xué)習(xí)筆記(八)- 泛型的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
伊宁县| 马公市| 长丰县| 准格尔旗| 固安县| 高安市| 昆山市| 北川| 吉林省| 象山县| 彰武县| 侯马市| 安溪县| 崇文区| 沁源县| 蓝山县| 锡林浩特市| 象山县| 文登市| 石台县| 湖北省| 鄂托克前旗| 宝清县| 湘潭市| 安多县| 贵定县| 四会市| 威宁| 台东市| 屏山县| 南木林县| 大冶市| 明溪县| 长春市| 彰化市| 罗甸县| 娄烦县| 五指山市| 托克托县| 宽城| 成都市|