泛型的定义
解决类,接口 方法的复用性,以及对不特定数据类型的支持
泛型函数
function getData(value: string):string {
return value;
}
只能返回string类型的数据
如果想同时返回string和number类型的数据可以定义类型为any
但是any相当于放弃了类型检查,并且传入参数类型和返回参数类型可以不一致
function getAnyData(value: any):any {
return value;
}
使用泛型,传入的类型必须和返回的类型一致
function getTData<T>(value:T):T{
return value;
}
//指定参数必须是<>里面的类型
getTData<number>(123);
getTData<string>('4545');
泛型类
比如有一个返回最小值算法,需要同时支持返回数字和字符串类型,通过类的泛型来实现
普通的实现:
class MinClass {
list:number[] = [];
add(num:number) {
this.list.push(num);
}
min():number {
let min:number = this.list[0];
this.list.forEach((item:number) => {
if(item<min){
min = item;
}
})
return min;
}
}
var m = new MinClass();
m.add(25);
m.add(21);
m.add(13);
m.add(12);
console.log(m.min());
只能传入number类型,返回number类型。
泛型的实现:
class MinClass<T> {
list:T[] = [];
add(num:T):void {
this.list.push(num);
}
min():T {
let min = this.list[0];
this.list.forEach((item) => {
if(item < min){
min = item;
}
})
return min;
}
}
//实例化类,并指定了类的T代表的类型
var m2 = new MinClass<string>();
m2.add('a');
m2.add('c');
m2.add('b');
m2.add('d');
console.log(m2.min());
可以在实例化的时候指定不同的类型
泛型接口
回顾一下普通函数接口
interface ConfigFn{
(value:string,value2:string):string;
}
var setData: ConfigFn = function(value:string,value2:string):string {
return value+value2;
}
泛型函数接口
第一种写法
interface ConfigFn{
<T>(value:T):T;
}
var getData: ConfigFn = function<T>(value:T):T {
return value;
}
getData<string>('12346')
// getData<string>(12346);//错误写法
第二种写法
interface ConfigFn<T>{
(value:T):T;
}
function getData<T>(value:T):T {
return value;
}
// 调用这个接口的时候指定泛型为string类型
var myGetData:ConfigFn<string>=getData;
myGetData('15')
myGetData(15);//错误写法
把类当做参数的泛型类
class Article {
title: string | undefined;
desc: string | undefined;
status: number | undefined;
id: number | undefined;
}
class DB {
add(info: Article):boolean{
console.log(info);
return true;
}
}
let db = new DB();
let news = new Article();
news.title = "China";
news.desc = "Chinese";
news.status = 1;
console.log(db.add(news))
为了避免调用add方法传入不同类型的实参都要修改DB类的add的形参类型,使用泛型
class DB2<T> {
add(info: T):boolean{
console.log(info);
return true;
}
update(info:T,id:number): boolean{
info['id'] = id;
console.log(info);
return true;
}
}
// <Article>对传入数据进行校验
let db2 = new DB2<Article>();
db2.add(news)
定义类作为参数来约束传入的类型,不同类型的class调用add方法只需要在实例化的时候指定要传入的类型,不用再修改add方法的形参类型。
class ArticleCate {
titleCate: string |undefined;
descCate: string |undefined;
statusCate: number |undefined;
idCate:number|undefined;
constructor(params:{
titleCate: string |undefined,
descCate: string |undefined,
statusCate?: number |undefined
idCate?: number |undefined
}){
this.titleCate = params.titleCate;
this.descCate = params.descCate;
this.statusCate = params.statusCate;
}
}
var ac = new ArticleCate({
titleCate: 'China',
descCate: 'China desc'
});
// 把类当做参数传入泛型类,泛型类对传入的参数做校验
let db3 = new DB2<ArticleCate>();
console.log(db3.add(ac))// ArticleCate {title: "China", desc: "China desc", status: undefined}
console.log(db3.update(ac,123))// ArticleCate {title: "China", desc: "China desc", status: undefined, id: 123}