日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)TypeScript教程:TypeScript泛型

軟件工程中,我們不僅要創(chuàng)建一致的定義良好的API,同時也要考慮可重用性。 組件不僅能夠支持當前的數(shù)據(jù)類型,同時也能支持未來的數(shù)據(jù)類型,這在創(chuàng)建大型系統(tǒng)時為你提供了十分靈活的功能。

為三門峽等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務,及三門峽網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務為網(wǎng)站制作、成都網(wǎng)站制作、三門峽網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!

在像C#和Java這樣的語言中,可以使用泛型來創(chuàng)建可重用的組件,一個組件可以支持多種類型的數(shù)據(jù)。 這樣用戶就可以以自己的數(shù)據(jù)類型來使用組件。

泛型之Hello World

下面來創(chuàng)建第一個使用泛型的例子:identity函數(shù)。 這個函數(shù)會返回任何傳入它的值。 你可以把這個函數(shù)當成是echo命令。

不用泛型的話,這個函數(shù)可能是下面這樣:

function identity(arg: number): number {
    return arg;
}

或者,我們使用any類型來定義函數(shù):

function identity(arg: any): any {
    return arg;
}

雖然使用any類型后這個函數(shù)已經(jīng)能接收任何類型的arg參數(shù),但是卻丟失了一些信息:傳入的類型與返回的類型應該是相同的。 如果我們傳入一個數(shù)字,我們只知道任何類型的值都有可能被返回。

因此,我們需要一種方法使返回值的類型與傳入?yún)?shù)的類型是相同的。 這里,我們使用了 類型變量,它是一種特殊的變量,只用于表示類型而不是值。

function identity(arg: T): T {
    return arg;
}

我們給identity添加了類型變量T。 T幫助我們捕獲用戶傳入的類型(比如:number),之后我們就可以使用這個類型。 之后我們再次使用了 T當做返回值類型?,F(xiàn)在我們可以知道參數(shù)類型與返回值類型是相同的了。 這允許我們跟蹤函數(shù)里使用的類型的信息。

我們把這個版本的identity函數(shù)叫做泛型,因為它可以適用于多個類型。 不同于使用 any,它不會丟失信息,像第一個例子那像保持準確性,傳入數(shù)值類型并返回數(shù)值類型。

我們定義了泛型函數(shù)后,可以用兩種方法使用。 第一種是,傳入所有的參數(shù),包含類型參數(shù):

let output = identity("myString");  // type of output will be 'string'

這里我們明確的指定了Tstring類型,并做為一個參數(shù)傳給函數(shù),使用了<>括起來而不是()。

第二種方法更普遍。利用了類型推論 -- 即編譯器會根據(jù)傳入的參數(shù)自動地幫助我們確定T的類型:

let output = identity("myString");  // type of output will be 'string'

注意我們沒必要使用尖括號(<>)來明確地傳入類型;編譯器可以查看myString的值,然后把T設(shè)置為它的類型。 類型推論幫助我們保持代碼精簡和高可讀性。如果編譯器不能夠自動地推斷出類型的話,只能像上面那樣明確的傳入T的類型,在一些復雜的情況下,這是可能出現(xiàn)的。

使用泛型變量

使用泛型創(chuàng)建像identity這樣的泛型函數(shù)時,編譯器要求你在函數(shù)體必須正確的使用這個通用的類型。 換句話說,你必須把這些參數(shù)當做是任意或所有類型。

看下之前identity例子:

function identity(arg: T): T {
    return arg;
}

如果我們想同時打印出arg的長度。 我們很可能會這樣做:

function loggingIdentity(arg: T): T {
    console.log(arg.length);  // Error: T doesn't have .length
    return arg;
}

如果這么做,編譯器會報錯說我們使用了arg.length屬性,但是沒有地方指明arg具有這個屬性。 記住,這些類型變量代表的是任意類型,所以使用這個函數(shù)的人可能傳入的是個數(shù)字,而數(shù)字是沒有 .length屬性的。

現(xiàn)在假設(shè)我們想操作T類型的數(shù)組而不直接是T。由于我們操作的是數(shù)組,所以.length屬性是應該存在的。 我們可以像創(chuàng)建其它數(shù)組一樣創(chuàng)建這個數(shù)組:

function loggingIdentity(arg: T[]): T[] {
    console.log(arg.length);  // Array has a .length, so no more error
    return arg;
}

你可以這樣理解loggingIdentity的類型:泛型函數(shù)loggingIdentity,接收類型參數(shù)T,和函數(shù)arg,它是個元素類型是T的數(shù)組,并返回元素類型是T的數(shù)組。 如果我們傳入數(shù)字數(shù)組,將返回一個數(shù)字數(shù)組,因為此時T的的類型為number。 這可以讓我們把泛型變量T當做類型的一部分使用,而不是整個類型,增加了靈活性。

我們也可以這樣實現(xiàn)上面的例子:

function loggingIdentity(arg: Array): Array {
    console.log(arg.length);  // Array has a .length, so no more error
    return arg;
}

使用過其它語言的話,你可能對這種語法已經(jīng)很熟悉了。 在下一節(jié),會介紹如何創(chuàng)建自定義泛型像 Array一樣。

泛型接口

我們來到了泛型接口;讓我們創(chuàng)建一個泛型接口來與 identities() 一起使用:

interface Identities {
   id1: V,
   id2: W
}

我在這里使用 V 和 W 作為類型變量來表示任何字母(或有效的字母和數(shù)字名稱的組合)都是可以的——除了用于常規(guī)目的之外,它們的名稱沒有任何意義。

現(xiàn)在,我們可以將這個接口應用為 identities()的返回類型,并稍稍修改返回類型去迎合它。我們還可以 console.log 這些參數(shù)和它們的類型,以便進一步說明:

function identities (arg1: T, arg2: U): Identities {
   console.log(arg1 + ": " + typeof (arg1));
   console.log(arg2 + ": " + typeof (arg2));
   let identities: Identities = {
    id1: arg1,
    id2: arg2
  };
  return identities;
}

我們現(xiàn)在 identities() 所做的是將類型 T 和 U 傳遞到函數(shù)和 Identities 接口中,使我們能夠定義與參數(shù)類型相關(guān)的返回類型。

注意:如果編譯 TS 項目并查找泛型,則不會找到任何泛型。由于在 Javascript 中不支持泛型,所以在編譯器生成的構(gòu)建中不會看到泛型。泛型純粹是用于編譯時的開發(fā)安全網(wǎng),它將確保代碼的類型安全抽象。

泛型類

泛型類看上去與泛型接口差不多。 泛型類使用( <>)括起泛型類型,跟在類名后面。

class GenericNumber {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

GenericNumber類的使用是十分直觀的,并且你可能已經(jīng)注意到了,沒有什么去限制它只能使用number類型。 也可以使用字符串或其它更復雜的類型。

let stringNumeric = new GenericNumber();
stringNumeric.zeroValue = "";
stringNumeric.add = function(x, y) { return x + y; };

alert(stringNumeric.add(stringNumeric.zeroValue, "test"));

與接口一樣,直接把泛型類型放在類后面,可以幫助我們確認類的所有屬性都在使用相同的類型。

我們在類那節(jié)說過,類有兩部分:靜態(tài)部分和實例部分。 泛型類指的是實例部分的類型,所以類的靜態(tài)屬性不能使用這個泛型類型。

泛型約束

你應該會記得之前的一個例子,我們有時候想操作某類型的一組值,并且我們知道這組值具有什么樣的屬性。 在loggingIdentity例子中,我們想訪問arglength屬性,但是編譯器并不能證明每種類型都有length屬性,所以就報錯了。

function loggingIdentity(arg: T): T {
    console.log(arg.length);  // Error: T doesn't have .length
    return arg;
}

相比于操作any所有類型,我們想要限制函數(shù)去處理任意帶有.length屬性的所有類型。 只要傳入的類型有這個屬性,我們就允許,就是說至少包含這一屬性。 為此,我們需要列出對于T的約束要求。

為此,我們定義一個接口來描述約束條件。 創(chuàng)建一個包含 .length屬性的接口,使用這個接口和extends關(guān)鍵字還實現(xiàn)約束:

interface Lengthwise {
    length: number;
}

function loggingIdentity(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}

現(xiàn)在這個泛型函數(shù)被定義了約束,因此它不再是適用于任意類型:

loggingIdentity(3);  // Error, number doesn't have a .length property

我們需要傳入符合約束類型的值,必須包含必須的屬性:

loggingIdentity({length: 10, value: 3});

在泛型約束中使用類型參數(shù)

你可以聲明一個類型參數(shù),且它被另一個類型參數(shù)所約束。比如,

function find>(n: T, s: U) {
  // ...
}
find (giraffe, myAnimals);

在泛型里使用類類型

在 TypeScript 使用泛型創(chuàng)建工廠函數(shù)時,需要引用構(gòu)造函數(shù)的類類型。比如,

function create(c: {new(): T; }): T {
    return new c();
}

一個更高級的例子,使用原型屬性推斷并約束構(gòu)造函數(shù)與類實例的關(guān)系。

class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function findKeeper (a: {new(): A;
    prototype: {keeper: K}}): K {

    return a.prototype.keeper;
}

findKeeper(Lion).nametag;  // typechecks!

分享文章:創(chuàng)新互聯(lián)TypeScript教程:TypeScript泛型
新聞來源:
http://m.5511xx.com/article/cojdehs.html