21、TypeScript 实战 - 类中的泛型

类中的泛型使用:

我们在写一个基本class类 在构造函数中需要传递一组女角色的名称,然后通过getGirlsNmae发方法展示女角色的名称

class GirlRole{
   
     
    constructor(private girls:string[]){
   
     }
    getGirlsNmae(index:number):string{
   
     
        return this.girls[index]
    }
}
let girl = new GirlRole(["虚空之女","希维尔","暗影猎手","霞"])
girl.getGirlsNmae(1)
console.log(girl.getGirlsNmae(1))
//终端控制台打印结果:希维尔

现在更好的保护角色的私密性,这些角色使用编号了,那我们程序就应该这样修改一下

class GirlRole{
   
     
    constructor(private girls:string[]|number[]){
   
     }
    getGirlsNmae(index:number):string|number{
   
     
        return this.girls[index]
    }
}
let girl = new GirlRole(["虚空之女","希维尔","暗影猎手","霞"])
girl.getGirlsNmae(1)
console.log(girl.getGirlsNmae(1))

很显然上述的代码是没有问题,但不够优雅,代码看起来比较复杂
这个时候可以使用泛型来解决这个问题,在我们日常编写发杂的代码时候 泛型是经常被使用的

class GirlRole<T>{
   
     
    constructor(private girls:T[]){
   
     }
    getGirlsNmae(index:number):T{
   
     
        return this.girls[index]
    }
}
let girl = new GirlRole(["虚空之女","希维尔","暗影猎手","霞"])
girl.getGirlsNmae(1)
console.log(girl.getGirlsNmae(0))
//终端控制台输出结果:虚空之女

我们使用了泛型,程序也没有报错,但是你会发现我们在实例化对象的时候,类型是通过推断出的
我们说过在使用了泛型,最好不要使用类型推断
所以我们可以这样写

	 let girl = new GirlRole<string>(["虚空之女","希维尔","暗影猎手","霞"])

泛型中的继承:

现在需求又变了,要求返回是一个对象中的roleName,也就是下面的代码要改成这个样子。

getGirlsNmae(index:number):string{
   
     
    return this.girls[index].roleName
}

之前的代码肯定是报错的
但是这时候还要求我们这么做,意思就是说传递过来的值必须是一个对象类型的,里边还要有roleName属性。
这时候就要用到继承了,我用接口的方式来实现。写一个Role的接口,每个接口里都要有 roleName 属性。代码如下:

interface Role{
   
     
    roleName:string
}

有了接口我们可以使用extends关键字实现泛型的继承

class GirlRole extends Role{
   
     
  ...
 }

这句代码的意思是泛型里必须有一个roleName属性,因为它继承了Role接口。
这时候应该是一个string类型才对,所以代码应该改为下面的样子:

interface Role{
   
     
    roleName:string
}

class GirlRole <T extends Role>{
   
     
    constructor(private girls:T[]){
   
     }
    getGirlsNmae(index:number):string{
   
     
        return this.girls[index].roleName
    }
}
let girlRole = new GirlRole([
    {
   
     roleName:"虚空之女"},
    {
   
     roleName:"希维尔"},
    {
   
     roleName:"暗影猎手"},
    {
   
     roleName:"霞"},
])
girlRole.getGirlsNmae(0)
console.log(girlRole.getGirlsNmae(0))
//打印结果:虚空之女

泛型的约束:

现在的泛型可以是任意类型,可以是对象、字符串、布尔、数字都是可以的。
但现在要求这个泛型必须是string或者number类型。我们还是拿上面的例子,不过把代码改为最初的样子。

class GirlRole <T>{
   
     
    constructor(private girls:T[]){
   
     }
    getGirlsNmae(index:number):T{
   
     
        return this.girls[index]
    }
}
let girl = new GirlRole(["虚空之女","希维尔","暗影猎手","霞"])

然后进行约束,这时候还是可以使用关键字extends来进行约束,把代码改成下面的样子

class GirlRole <T extends string|number>{
   
     
    constructor(private girls:T[]){
   
     }
    getGirlsNmae(index:number):T{
   
     
        return this.girls[index]
    }
}
 let girl = new GirlRole(["虚空之女","希维尔","暗影猎手","霞"])

上面就是最基本泛型讲解,在实际工作中,泛型的应用更广泛更复杂
一起学习,一起加油!!!