TypeScript泛型、泛型变量、泛型类、泛型接口、把类作为参数类型的泛型类

泛型

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

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

 泛型的特点

  1. 支持多种类型的数据(不特定的数据类型)。
  2. 传入的类型与返回的类型应该是相同的。
  3. 使用类型变量且指标是类型,不是值。
  4. 泛型的类型取决于调用的时候传入的参数类型。
  5. 对不特定类型数据的校验。

不用泛型的话,这个函数可能是下面这样:

function identity(arg: number): number {
    return arg;
}

或者,我们使用any类型来定义函数:

function identity(arg: any): any {
    return arg;
}

这里存在一个问题,就是如果返回值是any会导致这个函数可以接收任何类型的arg参数,即any放弃了类型检查,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。

因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。

function identity<T>(arg: T): T {
    return arg;
}

泛型的两种使用

定义了泛型函数后,可以用两种方法使用:

  1. 传入所有的参数,包含类型参数:
let output = identity<string>("myString");  // type of output will be 'string'

   这里我们明确的指定了Tstring类型,并做为一个参数传给函数,使用了<>括起来而不是()

  2.利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型

let output = identity("myString");  // type of output will be 'string'

泛型类

class MinClass<T>{
    public  list:T[] = [];
    add(value:T):void{
        list.push(value);
    }
    min():T{
        let minValue  = list[0];
        for(var i = 0;i<this.list.length;i;i++){
            if(minNum>this.list[i]){
                minNum = this.list[i];
            }
        }
    }

}


var m1 = new MinClass<number>(); //实例化类,并且规定类的T(泛型)代表number
m1.add(12);
m1.add(3);
m1.add(9);
alert(m1.min());//3


var m2 = new MinClass<string>(); //实例化类,并且规定类的T(泛型)代表string
m2.add(c);
m2.add(a);
m2.add(b);
alert(m2.min());//a

泛型接口

首先定义一个函数类型接口

//定义一个非泛型的函数类型接口
interface ConfigFn{
    (value1:string,value2:string):string;
}

var setData:Config = function(value1:string,value2:string):string{
    return value1+value2;
}

setData('name','zsf');

很明显这种函数类型借口函数的传入参数只能是string

所以为了解决以上问题,引入泛型接口:

第一种定义泛型接口的方法:

//定义一个泛型函数类型的接口
interface ConfigFn{
    <T>(value:T):T;
}

var getData:ConfigFn = function(value:T):T{
    return value;
}

getData<string>('zsf');

getData<number>(123);

第二种定义泛型接口的方法:

//定义一个泛型函数类型的接口
interface ConfigFn<T>{
    (value:T):T;
}

var getData:ConfigFn<T> = function(value:T):T{
    return value;
}

var mygetData1:ConfigFn<string>=getData;

mygetData1:ConfigFn<string>(‘20’);


var mygetData2:ConfigFn<number>=getData;

mygetData2:ConfigFn<string>(20);

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

  1. 定义一个类
  2. 把类作为参数来约束传入的类型
/*
定义一个User的类,这个类的作用就是映射数据库字段
让后定义一个mysqlDb的类,这个类用于操作数据库
然后把User类作为参数传到MysqlDb中
*/

class User{
    username:string | undefined;
    password:string | undefined;
}

class MysqlDb{
    //用User类来检验传入的对象的合法性
    add(user:User):boolean{
        console.log(user);
        return true;
    }
}

var u = new User();
u.username = 'wj';
u.password = '我最帅';

var Db   = new MysqlDb();
Db.add(u);

此时User 对象能够顺利存入,但是如果 要传个其他类型的对象,比如说要传一个文章类型的对象,那MysqlDb 就要重新定义数据类型,很显然,这样做不满足泛型,所以要重新定义Mysql类。

class MysqlDb<T>{
    //用User类来检验传入的对象的合法性
    add(info:T):boolean{
        console.log(info);
        return true;
    }
}

class User{
    username:string | undefined;
    password:string | undefined;
}

var u = new User();
u.username = 'wj';
u.password = '我最帅';

var Db   = new MysqlDb<User>();
Db.add(u);


class ArticleCate{

    title:string | undefined;
    desc:string | undefined;
    status:number | undefined;
    
    constructor(params:{
        title:string | undefined,
        desc:string | undefined,
        status?:number | undefined
    }){
        this.title = title;
        this.desc  = desc;
        this.status = status;
    }
}


var at =  new ArticleCate({
     title:'武侠',
     desc:'张三丰成神之路'
});

var aDb =  new  MysqlDb<ArticleCate>();
aDb.add(at); 

 

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读