TypeScript

  • 泛型的定义
  • 泛型接口
  • 把类作为参数类型的泛型类




泛型:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时,为我们提供了十分灵活的功能。

在像C#和Java这样的语言中,就可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以用自己的数据类型来使用组件。

通俗理解:泛型就是解决 类 接口 方法 的复用性、以及对不特定数据类型的支持。


泛型的定义

首先先来看一下泛型的使用场景。

使用普通函数,它只能返回一个类型的数据。

function getData(value:string):string{
    return value;
}

使用函数重载,代码冗余很明显。

function getInfo(name:string):string;
function getInfo(age:number):number;
function getInfo(str:any):any{
    if(typeof str === "string"){
        return "我是:"+str;
    }else{
        return "我的年龄:"+str;
    }
}

直接使用any,当然可以解决问题。

function getAny(value:any):any{
    return value;
}

但这么做,首先它和js就无区别了,ts的优势根本没有展现,使用any相当于放弃了类型检查。其次,这么做完全没有任何限制,就算数据传错也不会报错,
这显然不是我们想要的。那现在,我就想在传入number时返回number,同时也可以在传入string时返回string,就需要泛型。

泛型:可以支持不特定的数据类型,实现复用性。

// 这里的T表示泛型,(当然可以用其它字母,推荐T)
// 具体什么类型是调用这个方法的时候决定的
function getData<T>(value:T):T{
    return value;
}
console.log(getData<number>(123));
// 泛型相比于any的优势:存在类型检查
// 报错:getData<number>('123');

那么在泛型中需要注意的就是,上面代码中的return时不能给一个具体数据类型的值,因为传进来的数据类型和返回值的数据类型不一定相同,所以会报错。
那我们想改变一下返回值的数据类型,只需要:

function getData<T>(value:T):any{
    return value;
}

简例:

class MinClass<T>{
    public list:T[] = [];
    add(value:T):void{
        this.list.push(value);
    }
    min():T{
        let minNum = this.list[0];
        for(let i = 0; i < this.list.length; i++){
            if(minNum > this.list[i]){
                minNum = this.list[i];
            }
        }
        return minNum;
    }
}
// 制定了T代表number
let m = new MinClass<number>();
m.add(1);
m.add(2);
console.log(m.min());
// 制定了T代表string
let s = new MinClass<string>();
s.add('a')
s.add('c')
console.log(s.min())

泛型接口

使用方法一:

interface ConfigFn{
    <T>(value:T):T;
}
let getData:ConfigFn = function<T>(value:T):T{
    return value;
}
console.log(getData<string>('李四'));

使用方法二:

interface ConfigFn<T>{
    (value:T):T;
}
function getData<T>(value:T):T{
    return value;
}
let myGetData:ConfigFn<string> = getData;
console.log(myGetData('张三'));

把类作为参数类型的泛型类

// 模拟操作数据库的泛型类
class MysqlDb<T>{
    add(info:T):boolean{
        console.log(info);
        return true;
    }
}

class User{
    username: string;
    password: string;
}
let u = new User();
u.username = '李四';
u.password = '123456';
// 类当作参数的泛型类
let Db = new MysqlDb<User>();
Db.add(u);

class ArtCate{
    title: string;
    desc: string;
    constructor(params:{
        title: string,
        desc?: string
    }) {
        this.title = params.title;
        this.desc = params.desc;
    }
}
let a = new ArtCate({
    title: '标题',
    desc: '描述'
});
// 类当作参数的泛型类
let Db2 = new MysqlDb<ArtCate>();
Db2.add(a);