TypeScript學習: 九、TypeScript的泛型


泛型的定義

 泛型, 軟件開發過程中,我們不僅要創建一致的定義良好的api, 同時也要考慮可重用性。 組件不僅能夠支持當前的數據類型,同時也能支持未來的數據類型,這在創建大型系統時為你提供十分靈活的功能。
 
在像C#和java這樣的語言中,可以使用泛型來創建可重用的組件, 一個組件可以支持多種數據類型的數據。這樣用戶就可以以自己的數據類型來使用組件。
 
 通俗理解, 泛型就是解決 類 接口 方法的復用性、以及對不特定數據類型的支持
 

泛型函數

 有一個需求: 傳入指定的參數類型 返回這個指定的參數類型    比如 要求參數類型是 string 返回 string  要求參數類型是 number返回 number

// 只能返回string 的函數
function getData(val:string):string{
return val + "返回字符串";
}
//  只能返回number 的函數
function getData1(val:number):number{
    return val; // 返回數字
}

 

  這里用了兩個函數去實習功能,如果還需要返回  bloolean 類型是不是還需要再添加多一個函數去實現, 這樣實現的話會出現了代碼的冗余

 有人就會想到用any類型去實現功能,

function getData2(val:any):any{
    return 123; // 返回number
}
getData2("string");

  用any可以實現功能, 但是會出現這樣的錯誤, 我傳入string類型, 返回了number ,不符合要求, 並且使用any類型就是拋棄typeScript的初衷了,放棄了類型檢查

使用泛型解決問題:泛型可以支持不特定類型, 實現要求傳入類型和返回的類型一致

 // T 表示泛型, 具體什么類型是調用的時候決定的
function getData<T>(val:T):T{
    return val;
}
// 調用:
// number類型, 返回number 類型
getData<number>(100);

// string 類型
getData<string>("張三");

getData<boolean>(123); // 錯誤寫法 定義Boolean類型,不能傳入number類型的參數

 

 如果要求函數返回必須為string類型的 泛型函數寫法:

 // 泛型函數, 指定返回string類型
function getData<T>(val:T):string{
    return val + "val";
}

getData<number>(234);

getData<string>("張三");

 

通過這兩個例子可以看出 泛型 T 代表的是一種數據類型, 具體是什么數據類型,就是要調用該方法的時候傳入指定的類型來確定的 。 

 getData<T>     getData<string>     該函數里面的所有T 都是泛型 

泛型類

需求:比如有個最小的堆算法, 需要同時支持返回數字和字符串兩種類型,  通過類的泛型來實現
// 不適用泛型類的寫法
class MinClass{
    public list:number[] = [];

    add(num:number):void{
        this.list.push(num);
    }
    min():number {
        var minNum = this.list[0];
        for(var i = 0; i < this.list.length; i++) {
            if(minNum > this.list[i]) {
                minNum = this.list[i];
            }
        }
        return minNum;
    }
}

var m = new MinClass();
m.add(2);
m.add(50);
m.add(1);
console.log(m.min());  // 輸出: 1

 這個列子可以實現的是number類型的最小堆算法,對於類型校驗,不能使用string的類型

看看 泛型類的實現

// 泛型類
class MinClass<T>{
    public list:T[] = [];

    add(num:T):void{
        this.list.push(num);
    }
    min():T {
        var minNum = this.list[0];
        for(var i = 0; i < this.list.length; i++) {
            if(minNum > this.list[i]) {
                minNum = this.list[i];
            }
        }
        return minNum;
    }
}

var m = new MinClass<number>(); // 實例化 類, 並且指定了泛型 的類型 為number
m.add(2);
m.add(50);
m.add(1);
console.log(m.min());  // 輸出: 1

var s = new MinClass<string>();
s.add("n");
s.add("a");
s.add("z");
console.log(s.min());  // 輸出: a    碼值計算

使用泛型了, 可以寫入number類型和string類型 

 

--- 泛型類--- 進階

  要求:定義一個類,把類當作參數,來約束傳入的數據類型

  實現:定義一個user的類,這個類的作用是映射數據庫字段, 然后定義個mysqlDb的類,用於操作數據庫,然后把User類當作參數傳入到mysqlDb執行

// 映射數據庫字段的實體類
class User{
    public username:string | undefined;
    public pasword:string | undefined;

    constructor() {

    }
}

// 數據庫操作類型
class MysqlDb{
    // 添加數據
    add(user:User):boolean{
        return true;
    }
    // 刪除數據
    // 修改數據
    // ----
}

var u = new User();
u.username = "張三";
u.pasword = "123";

var Db = new MysqlDb();

Db.add(u);  // 把這個user添加到數據庫中

 

 這個 MysqlDb 可以執行 user類 的添加等操作, 同樣的問題:這個MysqlDb 只能對user 類進行操作, 如果我還有其他的表:

 

class ArticleCate{
    title:string | undefined;
    desc:string | undefined;
    status:number | undefined;
    constructor() {

    }
}
// 數據庫操作類型
class MysqlDb{
    // 添加數據
    add(info:ArticleCate):boolean{
        console.log(info);
        return true;
    }
    // 刪除數據
    // 修改數據
    // ----
}
var art = new ArticleCate();
art.status = 1;
art.desc = "國內新聞";
art.title = "國內";
var Db = new MysqlDb();
Db.add(art);  // 把這個ArticleCate添加到數據庫中

是不是這樣就出現了代碼的冗余, 有多個要操作的實體類,就要定義多個  MysqlDb 去實現

來看看泛型如何實現, 把 MysqlDb  就封裝一次

// 映射數據庫字段的實體類
class User{
    public username:string | undefined;
    public pasword:string | undefined;

    constructor() {

    }
}

class ArticleCate{
    title:string | undefined;
    desc:string | undefined;
    status:number | undefined;
    constructor() {

    }
}

var art = new ArticleCate();
art.status = 1;
art.desc = "國內新聞";
art.title = "國內";
var DbArt = new MysqlDb<ArticleCate>(); // 直接實例化 mysqlDb
DbArt.add(art);  // 把這個ArticleCate添加到數據庫中

var user = new User();
user.username = "張三";
user.pasword = "24123";
var DbUser = new MysqlDb<User>();
DbUser.add(user); // 把這個User添加到數據庫中
// DbUser.add(123); // 錯誤寫法, 有類型校驗

 

所以泛型, 不僅可以代表基本數據類型, 也可以是定義的類

 

泛型接口

先來看一個函數接口

 // 函數接口
interface ConfigFn{
    (val: string, val2: string):string;
}
// 實現接口
var getData:ConfigFn = function(val1:string, val2:string):string{
    return val1 + val2;
}

var str:string = getData("張三", "李四");

console.log(str);

 

 再來看看泛型接口

 // 泛型函數接口
interface ConfigFn{
    <T>(val: T, val2: T):T;
}
// 實現泛型函數接口
var getData:ConfigFn = function<T>(val1:T, val2:T):T{
    return val1;
}

var str:string = getData<string>("張三", "李四");

console.log(str);

 

 實現泛型接口的時候, 不指定泛型類型, 到調用的時候再指定類型

另外一種寫法

// 泛型函數接口的另外一種寫法
interface ConfigFn<T> {
    (val: T, val2: T):T;
}

// 定義函數
function getData<T>(val1:T, val2:T):T{
    return val1;
}
// 實現接口, 並且指定類型
var myGetData:ConfigFn<string> = getData; 

myGetData("張三", "李四");

注意: 實現泛型接口,本身也要是一個泛型

 

 

有了泛型, 調用方法的時候,同樣的代碼,可供多個類型使用,大大的擴展了代碼的復用性 

 

 

使用 類,接口,泛型, 實現SQL底層封裝

  sql 數據庫類的簡單功能有: 查詢, 添加, 修改, 刪除 ,先從這四個功能起封裝庫類, 先定義一個泛型接口

// 定義基礎接口
interface DBI<T>{
    add(info:T): boolean; update(info:T,id:number): boolean; delete(id:number): boolean; get(id:number): any[]; }

 

  簡單實現接口, 注意: 要實現泛型接口, 這個類也是必須是泛型類

// 定義一個操作mysql數據庫類, 實現接口, 注意要實現泛型接口, 這個類也是泛型類
class MysqlDb<T> implements DBI<T> {
    constructor() {
        // 數據庫建立連接-------
      }

    add(info: T): boolean { throw new Error("Method not implemented."); } update(info: T, id: number): boolean { throw new Error("Method not implemented."); } delete(id: number): boolean { throw new Error("Method not implemented."); } get(id: number): any[] { throw new Error("Method not implemented."); } } // 實現sqlserver 的數據庫類 class SqlserverDb<T> implements DBI<T> {
    constructor() {
        // 數據庫建立連接-------
     }

    add(info: T): boolean { throw new Error("Method not implemented."); } update(info: T, id: number): boolean { throw new Error("Method not implemented."); } delete(id: number): boolean { throw new Error("Method not implemented."); } get(id: number): any[] { throw new Error("Method not implemented."); } }

 

實現mysql數據類操作User數據表,, 使用泛型, 把類當作參數來約束方法

// 定義實體類, 映射數據庫表的類
class User{
    id: number | undefined; userName:string | undefined; password:string | undefined; } var user = new User(); user.id = 1; user.userName = "tom"; user.password = "12345678"; // 實現user類的數據庫操作 var UserMysql = new MysqlDb<User>();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM