typescript中的泛型
-
泛型的定义:
软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。
通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)//只能返回string类型的数据 //function getData(value:string):string{ // return value; //} //同时返回string和number类型 (代码冗余) //function getData1(value:string):string{ // return value; //} //function getData2(value:string):string{ // return value; //} //同时返回string和number类型 any可以解决这个问题 //function getData(value:any):any{ // return value; //} //any放弃了类型的检查,传入什么,返回什么。比如:传入number类型必须返回number类型 //function getData(value:any):any{ //传入的参数和返回的类型可以不一致 // return "aaa"; //}
-
泛型函数:
可以支持不特定的数据类型,要求:传入的参数和返回的类型一致//T表示泛型,具体什么类型是调用这个方法的时候决定的 function getData<T>(value:T):T{ return value; } //getData<number>("123")//错误写法。报错 getData<string>("123") getData<number>(123)
-
泛型类:
比如有个最小的堆算法,需要同时返回数字和字符串的两种类型。通过类的泛型来实现//普通类 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(3); m.add(22); m.add(2); console.log(m.min()); //2
//类的泛型: class MinClass<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 MinClass<number>(); //实例化类,并且指定了T代表的类型number m1.add(3); m1.add(23); m1.add(2); console.log(m1.min()); //2 var m2 = new MinClass<string>(); //实例化类,并且指定了T代表的类型是string m2.add("a"); m2.add("b"); m2.add("c"); console.log(m2.min()); //a
范类:泛型可以帮助我们避免重复的代码以及对不特定数据类型的支持(类型校验)
a. 定义个类//操作数据库的泛型类 class mysqlDb<T>{ add(info:T):boolean{ console.log(info); return true; } } //想给user表增加数据 //定义一个user类和数据库进行映射 class User{ username:string | undefined; pasword:string | undefined; } var u = new User(); u.username = "张三"; u.pasword = "123456"; var Db = new mysqlDb<User>(); Db.add(u);//{username:"张三",pasword:"123456"}
class mysqlDb<T>{ //添加数据 add(info:T):boolean{ console.log(info); return true; } //修改数据 updated(info:T,id:number):boolean{ console.log(info); console.log(id); return true; } } class ArticleCate{ title:string | undefined; desc:string | undefined; status:number | undefined; constructor(params:{ title:string | undefined, desc:string | undefined, status?:number | undefined }){ this.title = params.title; this.desc= params.desc; this.status= params.status; } } //增加操作 //var a = new ArticalCate({ // title:"分类", // desc:"11111", // status:1 //}) //var Db = new mysqlDb<AricleCate>(); //Db.add(a); //{title:"分类",desc:"11111",status:1} var b = new ArticalCate({ title:"分类", desc:"11111", }); b.status=0; var Db = new mysqlDb<AricleCate>(); Db.updated(a,12);//{title:"分类",desc:"11111",status:0} 12
b. 把类作为参数来约束数据传入的类型
class User{ username:string | undefined; pasword:string | undefined; } class MysqlDb{ add(user:User):boolean{ console.log(user); return true; } } var u = new User(); u.username="aaa"; u.pasword="123456"; var Db = new MysqlDb(); Db.add(u);
class ArticleCate{ title:string | undefined; desc:string | undefined; status:number | undefined; } class MysqlDb{ add(user:ArticleCate):boolean{ console.log(user); return true; } } var u = new User(); u.title="国内"; u.desc="国内新闻"; u.status=1; var Db = new MysqlDb(); Db.add(u);//{title:"国内",desc:"国内新闻",status:1}
-
泛型接口:
//定义接口(函数类型接口) interface ConfigFn{ (value1:string,value2:string):string; } //实现接口 var setData:ConfigFn=function(value1:string,value2:string):string{ return value1+value2; } setData("name","张三")
//泛型接口1: interface ConfigFn{ <T>(value:T):T; } var getData:ConfigFn = function<T>(value:T){ return value; } getData<string>("张三") //泛型接口2: interface ConfigFn<T>{ (value:T):T; } function getData2<T>(value:T){ return value; } var myGetData:ConfigFn<string> = getData2; myGetData("张三")