TypeScript泛型、泛型變量、泛型類、泛型接口、把類作爲參數類型的泛型類

泛型

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

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

 泛型的特點

  1. 支持多種類型的數據(不特定的數據類型)。
  2. 傳入的類型與返回的類型應該是相同的。
  3. 使用類型變量且指標是類型,不是值。
  4. 泛型的類型取決於調用的時候傳入的參數類型。
  5. 對不特定類型數據的校驗。

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

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

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

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

這裏存在一個問題,就是如果返回值是any會導致這個函數可以接收任何類型的arg參數,即any放棄了類型檢查,這樣就丟失了一些信息:傳入的類型與返回的類型應該是相同的。如果我們傳入一個數字,我們只知道任何類型的值都有可能被返回。

因此,我們需要一種方法使返回值的類型與傳入參數的類型是相同的。 這裏,我們使用了 類型變量,它是一種特殊的變量,只用於表示類型而不是值。

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

泛型的兩種使用

定義了泛型函數後,可以用兩種方法使用:

  1. 傳入所有的參數,包含類型參數:
let output = identity<string>("myString");  // type of output will be 'string'

   這裏我們明確的指定了Tstring類型,並做爲一個參數傳給函數,使用了<>括起來而不是()

  2.利用了類型推論 -- 即編譯器會根據傳入的參數自動地幫助我們確定T的類型

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

泛型類

class MinClass<T>{
    public  list:T[] = [];
    add(value:T):void{
        list.push(value);
    }
    min():T{
        let minValue  = list[0];
        for(var i = 0;i<this.list.length;i;i++){
            if(minNum>this.list[i]){
                minNum = this.list[i];
            }
        }
    }

}


var m1 = new MinClass<number>(); //實例化類,並且規定類的T(泛型)代表number
m1.add(12);
m1.add(3);
m1.add(9);
alert(m1.min());//3


var m2 = new MinClass<string>(); //實例化類,並且規定類的T(泛型)代表string
m2.add(c);
m2.add(a);
m2.add(b);
alert(m2.min());//a

泛型接口

首先定義一個函數類型接口

//定義一個非泛型的函數類型接口
interface ConfigFn{
    (value1:string,value2:string):string;
}

var setData:Config = function(value1:string,value2:string):string{
    return value1+value2;
}

setData('name','zsf');

很明顯這種函數類型藉口函數的傳入參數只能是string

所以爲了解決以上問題,引入泛型接口:

第一種定義泛型接口的方法:

//定義一個泛型函數類型的接口
interface ConfigFn{
    <T>(value:T):T;
}

var getData:ConfigFn = function(value:T):T{
    return value;
}

getData<string>('zsf');

getData<number>(123);

第二種定義泛型接口的方法:

//定義一個泛型函數類型的接口
interface ConfigFn<T>{
    (value:T):T;
}

var getData:ConfigFn<T> = function(value:T):T{
    return value;
}

var mygetData1:ConfigFn<string>=getData;

mygetData1:ConfigFn<string>(‘20’);


var mygetData2:ConfigFn<number>=getData;

mygetData2:ConfigFn<string>(20);

把類作爲參數類型的泛型類

  1. 定義一個類
  2. 把類作爲參數來約束傳入的類型
/*
定義一個User的類,這個類的作用就是映射數據庫字段
讓後定義一個mysqlDb的類,這個類用於操作數據庫
然後把User類作爲參數傳到MysqlDb中
*/

class User{
    username:string | undefined;
    password:string | undefined;
}

class MysqlDb{
    //用User類來檢驗傳入的對象的合法性
    add(user:User):boolean{
        console.log(user);
        return true;
    }
}

var u = new User();
u.username = 'wj';
u.password = '我最帥';

var Db   = new MysqlDb();
Db.add(u);

此時User 對象能夠順利存入,但是如果 要傳個其他類型的對象,比如說要傳一個文章類型的對象,那MysqlDb 就要重新定義數據類型,很顯然,這樣做不滿足泛型,所以要重新定義Mysql類。

class MysqlDb<T>{
    //用User類來檢驗傳入的對象的合法性
    add(info:T):boolean{
        console.log(info);
        return true;
    }
}

class User{
    username:string | undefined;
    password:string | undefined;
}

var u = new User();
u.username = 'wj';
u.password = '我最帥';

var Db   = new MysqlDb<User>();
Db.add(u);


class ArticleCate{

    title:string | undefined;
    desc:string | undefined;
    status:number | undefined;
    
    constructor(params:{
        title:string | undefined,
        desc:string | undefined,
        status?:number | undefined
    }){
        this.title = title;
        this.desc  = desc;
        this.status = status;
    }
}


var at =  new ArticleCate({
     title:'武俠',
     desc:'張三丰成神之路'
});

var aDb =  new  MysqlDb<ArticleCate>();
aDb.add(at); 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章