Typescript的泛型/泛型接口
泛型
软件工程中,我们不仅要创建一致的定义良好的API,同时要考虑可重用性,组件不仅能够支撑当前的数据类型,同时也能支持未来的数据类型,这在创建大型项目时为你提供了十分灵活的功能, 像C#和java语言中,可以使用范型创建可重用的组件,一个组件可以支持多种类型的数据,这样的用户就可以自己的数据类型来使用组件。通俗来说:泛型就是解决类、接口、方法的复用性、以及不特定数据类型的支持。
泛型的定义和函数
// 只能返回string类型的数据 function getData(value:string):string { return value } // 同时能返回string类型和number类型, 当要返回string类型时使用getData(冗余) function getData1(value:number):number { return value } // ts的其他的方式,实现放回string、number类型 function getData3(value:any):any { return value // 但是有一个问题就是,无法实现类型检查和约束,你也不知道传入和返回是否时一致的 } // 我们必须要实现一个方法传入什么类型,必须返回什么类型,这就可以使用范型了 function getData4<T>(value:T):T{ // 这里的T就是泛型,这里的T不一定时T,也可以是时A、B、C return value } // 使用泛型 alert(getData4<number>(123)) // 约束传入和返回的类型为number getData4<string>('1111') // 约束传入和返回的类型为string function getData5<T>(value:T):any{ // 这里的T就是泛型,返回值为any return value } getData5<string>('1111')
demo:比如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现
class MinClass { public list:number[]=[]; add(num:number){ 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(12); m.add(33); m.add(52); alert(m.min()) // 上面的代码是可以传入数值返回最小值,那如果我想传入a-z的字符,能否返回其中最小的 class MinClass1<T> { // 泛型类 public list:T[] = []; add(value:T):void { this.list.push(value) } 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 m1 = new MinClass1<string>(); // 这里的泛型是string,当然也可以是number m1.add('a'); m1.add('A') m1.add('b') alert(m1.min())
泛型接口
// 函数类型接口 interface ConfigFn { (value1:string,value2:string):string // 函数接口 } var setData:ConfigFn = function(value1:string, value2:string):string{ return value1+value2 } alert(setData('name','wangwu')) // 韩式类型接口实现 // 第一种定义方式:泛型接口 interface ConfigFns { <T>(value1:T):T; // 泛型接口 } var getData:ConfigFns = function<T>(value1:T):T{ return value1 } getData<string>("OK") // 第二种定义方式 interface ConfigFnplus<T> { (value1:T):T; // 泛型接口 } function getData1<T>(value1:T):T{ return value1 } var myGetData:ConfigFnplus<string> = getData1 myGetData("OK,wo")
泛型小demo:
功能: 定义一个操作数据库的库,支持Mysql、 Mssql、Mongdb,要求Mysql、Mssql、Mongdb功能一样,都有add、update、delete、get方法
注意:约束统一规范,以及代码的重用,解决方案:需要约束规范所以要定义接口,接口是一种规范定义,它定义了行为和动作的规范;泛型通俗理解:泛型就是解决类、接口方法的复用性。
// 定义接口 interface DBI<T>{ add(info:T):boolean; update(info:T,id:number):boolean; delete(id:number):boolean; get(id:number):any[]; } // 实现mongdb类 class MongDb<T> implements DBI<T> { add(info: any): boolean { console.log(info) return true } update(info: any, 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数据库的类,注意:要实现泛型接口,这个类应该是一个泛型类 class MysqlDb<T> implements DBI<T>{ constructor(){ console.log('数据库实现连接') } add(info: T): boolean { console.log(info) return true } 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."); } } // 操作用户表, 定义一个user类和数据表做映射 class User{ username:string|undefined; password:string|undefined; } var u = new User(); u.username='张三'; u.password='123' //var oMysql = new MysqlDb(); // 类作为参数约束数据传入的类型 var oMysql = new MysqlDb<User>(); // 通过指定类型去校验参数 oMysql.add(u); // 这里的u是实现了验证的