我知道ts支持范型,但是因为几乎用不到,所以对于范型对我来说往往蒙上一层神秘色彩。

最近我才真正的体会到范型的真正威力。

下面就介绍我的使用场景。

在和后端接口交互的时候, 后端接口返回的数据都是如下的类型。

interface XData {
    success: boolean
    total: number
    result: any[]
}

这里我把result定义为any类型,因为它的具体类型是由接口确定的。 比如查话单的接口是话单的结构类型,查订单的接口返回的是订单的类型。

interface CDR {
    id: number
    creatAt: string
}

interface Order {
    id: number
}

在不用范型的时候,我们要么定义如下两个interface

interface XDataCDR {
    success: boolean
    total: number
    result: CDR[]
}

interface XDataOrder {
    success: boolean
    total: number
    result: Order[]
}

在使用axios的时候,对于响应体的data, 可以使用如下的方式声明data

function getCDR (id) {
    return axios.get<XDataCDR>('/api/xxx' + id)
}

但是,如果我们稍微修改一下XData的类型声明,加上范型。 就不需要用到XDataCDR和XDataOrder两个接口。

interface XData<T> {
    success: boolean
    total: number
    result: T[]
}

function getCDR (id) {
    return axios.get<XData<CDR>>('/api/xxx' + id)
}

只需要用到XData<CDR>就可以构造出新的类型。

从上面可以看出范型实际上不是约束具体的值的,而是用来对类型进行约束。使用范型,可以减少大量重复的代码。

范型一般用于关键词之后,例如interface名之后,函数名之后。

例如:

interface X<T> {
    a: T
}

function say<T>() : T[] {
}

所以,有些功能,直到真正用到,才能真正理解。