Typescript-泛型

概念

TypeScript的泛型与其他面向对象的语言中的定义是相似的。泛型可以理解为在我们定义函数、接口或者类的时候,不预先指定其相关的类型,而是在使用的时候手动指定类型。这和TypeScript基础类型中的any是有区别的。点击免费学习

当我们不使用泛型的时候,可能就如下这样:

function show(name: string): string {

    return name;

}

function show(name: any): any {

    return name;

}

上面例子中用any或许没有什么问题,但是当我们想传入的参数类型和返回值类型相同时,使用any时的返回值就可能有多种情况了。还有就是我们平时也会考虑重用性,提取公共组件等。这时泛型就能派上了。下面是一个泛型函数的例子:

function show(arg: T): T {

    return arg;

}

这个show函数后面的 T ,叫做类型变量,这个我们后面会介绍。这个函数我们可以用两种方法调用。
第一种为传入参数,包括类型参数:

show("james"); //"james"

第二种为不包括类型参数,这种方式利用了类型推论,这个再后面的章节会讲到:

show(1); //1

泛型变量

上面所写的例子中,我们可以在“<>”中指定一个变量T,并且我们要把这个T定义在参数和返回值上。编译器在检查我们的代码的时候,我们必须在函数体中正确的使用这个通用的类型。

function show(arg: T): T {

    console.log(arg.length)  //错误,类型T不存在length属性

    return arg;

}

上面的例子中,我们在打印arg的length中报错了。原因是我们在使用这个函数的时候,传入的参数可能为数字,而数字是没有length属性的。
当然,我们在调用函数的时候也要正确调用:

function show(arg: T): T {

    return arg;

}

show(1); //错误,参数1的类型不是string

show<>(1); //错误,参数类型不能为空

针对数组:

function show(arg: T[]): T[] {

    return arg;

}

show(["奥","利","给"]);  //["奥", "利", "给"]

function show(arg: Array): Array {

    return arg;

}

show([6, 6, 6]); // [6, 6, 6]

泛型接口

如下所示:

interface IMan {

    (arg: T): T

}

function man(arg: T): T{

    return arg;

}

let showMan: IMan = man;

showMan("james"); //"james"

还有另外一种写法,这种方法我们可以把泛型参数当做整个接口的参数:

interface IMan {

    (arg: T): T

}

function man(arg: T): T{

    return arg;

}

let showMan: IMan = man;

showMan("james"); //"james"

这样的好处就是在使用时知道具体的参数类型了。

泛型类

我们可以使用(<>)和尖括号中间的变量,然后跟在类名的后面来表示泛型类。需要注意的是,泛型类指的是实例部分的类型,类的静态属性不能使用泛型类型。

class Man {

    name: T;

    constructor(arg: T) {

        this.name = arg;

    }

    play(a: T) : T {

        return a;

    }

     

}

let showMan = new Man("James");

showMan.name;  //"James"

showMan.play("ball"); //"ball"

也可以稍微复杂一点:

class Man {

    name: T;

    sum: T[];

     

    constructor(arg: T) {

        this.name = arg;

        this.sum = [];

         

    }

    push(item: T): void{

        this.sum.push(item)

    }

    output() {

         return this.sum;

    }

}

let showMan = new Man("James");

showMan.push("one for all");

showMan.output(); //["one for all"]

泛型约束

让我们回到泛型变量一节中的一个例子:

function show(arg: T): T {

    console.log(arg.length)  //错误,类型T不存在length属性

    return arg;

}

如果我们想要使用length属性,那该怎么办?可以看下面的例子:

interface ILen {

    length: number;

 }

function show(arg: T): T {

    console.log(arg.length)  //没有报错了

    return arg;

}

虽然上面的例子没有再报错,但是因为这个泛型函数被定义了约束,所以我们再调用函数的时候又有了讲究,也就是我们在传值的时候需要像下面的例子一样:

interface ILen {

    length: number;

 }

function show(arg: T): T {

    console.log(arg.length) 

    return arg;

}

show(3); //错误,参数3不能分配给类型ILen

show({ length: 2 }); // 2  {length: 2}

show({length:2, arg:1}) //2  {length: 2, arg: 1}

show({length:2, arg:"james"}) //2 {length: 2, arg: "james"}

最后


文中有些地方可能会加入一些自己的理解,若有不准确或错误的地方,欢迎指出~

你可能感兴趣的:(web前端,typescript,javascript)