TypeScript中泛型的使用

泛型

对于typescript中的泛型,你可以把它理解为参数化类型,把每个参数的类型也封装成参数的形式,而这个封装的方式,就是泛型。

1.函数泛型

如果我们要编写一个函数,接收两个参数,这两个参数可能都为string类型或者都为number类型,最后做拼接操作。
对于这个功能,其实通过上面的联合类型以及类型保护就能实现,但是,我们再分析一下这个功能的条件,“这两个参数可能都为string类型或者都为number类型”,思考一下,我们能不能在调用的时候就直接告诉这个函数传进来的参数类型呢?答案是可以的,泛型就能实现这个功能。

function f<T>(one: T, two: T) {
    return `${one}${two}`
}
f<string>("ok", "fine")

这里再多提一嘴,由于typescript具有类型推断功能,所以我们在调用函数的时候甚至不需要写泛型中参数,比如这样:

f("ok", "fine")

当然,我们也可以定义多个泛型。

function f<T, P>(one: T, two: P) {
    return `${one}${two}`
}
f<string, number>("ok", 2)

2.类的泛型

初始化类的泛型

创建一个类,顺带把构造函数写好,两个参数:

class Student {
    constructor(private name: string, private age: number) { }
}

参数化参数的类型,实现对类的泛型初始化,之后实现一个简单的调用。

class Student<T, P> {
    constructor(private name: T, private age: P) { }
}
const stu = new Student<string, number>("小白", 21)

泛型的继承

接着上面Student的例子,现在有一个这样的数据结构:每一个Student都来源于一个Person接口,这个接口中有一个NAME属性(string类型),现在我们需要把一个Student对象中的NAME取出来。
首先我们完善一下interface以及getter函数的部分:

interface Person {
    NAME: string
}
class Student<T> {
    constructor(private name: T) { }
    get getName() {
        return this.name
    }
}

现在的接口Person和Student类还是没有任何关联的,接下来我们使用泛型的继承将Person中的NAME传递给Student中的name,大家在理解这一点的时候注意两个name的大小写,小写的是类中定义的,大写的是接口传递给类的

interface Person {
    NAME: string
}
class Student<T extends Person> {
    constructor(private name: T) { }
    get getName() {
        return this.name.NAME
    }
}

最后调用一下。

const stu = new Student({ NAME: "小白" })

如果大家观察的仔细,我们会发现我们在传递构造函数的时候直接传递进去了一个对象,是带着大括号的。原因其实很简单,我们可以将Person看作是一个要传进去的那个对象的描述,通过extends语句将这个描述传递给Student中的name属性,最后在我们初始化对象的时候,我们看似初始化的是一个对象,但其实我们初始化的还是构造函数中的那个name。
这个地方一开始看的我懵逼了很久,最后我照着别人的代码写了一个实例出来,又反复看了几遍就发现能看懂了。

猜你喜欢

转载自blog.csdn.net/qq_43592084/article/details/109542526