泛型的定義
泛型函數
有一個需求: 傳入指定的參數類型 返回這個指定的參數類型 比如 要求參數類型是 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> {
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> {
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>();