Typescript的泛型/泛型接口
泛型
软件工程中,我们不仅要创建一致的定义良好的 API,同时要考虑可重用性,组件不仅能够支撑当前的数据类型,同时也能支持未来的数据类型,这在创建大型项目时为你提供了十分灵活的功能, 像 C# 和 java 语言中,可以使用范型创建可重用的组件,一个组件可以支持多种类型的数据,这样的用户就可以自己的数据类型来使用组件。通俗来说:泛型就是解决类、接口、方法的复用性、以及不特定数据类型的支持。
泛型的定义和函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // 只能返回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:比如有个最小堆算法,需要同时支持返回数字和字符串两种类型,通过类的泛型来实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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()) |
泛型接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | // 函数类型接口 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 方法
注意:约束统一规范,以及代码的重用,解决方案:需要约束规范所以要定义接口,接口是一种规范定义,它定义了行为和动作的规范;泛型通俗理解:泛型就是解决类、接口方法的复用性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | // 定义接口 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是实现了验证的 |