[4] 泛型

27 阅读2分钟

是什么

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

定义的是类型,不是值。扩展函数,接口,类的功能。

优势&为什么使用泛型

  • 函数和类支持多种类型,增强程序扩展性。
  • 不必写多余的函数重载和冗长的联合类型声明,增强代码可读性。
  • 灵活控制类型之间的约束.

对于泛型的实践来说,使用是需要一定理解,复杂的泛型使用会非常的复杂。

经典例子

问题:定义了一个通用函数log,要求返回值的类型传入参数的类型是相同的。

方案一: 给输入参数value设置any类型,函数返回值类型也为any。
缺点: any会丢失信息,像第一个例子那像保持准确性,传入数值类型并返回数值类型。

function log(value: any): any {
    console.log(value)
    return value;
}

方案二:泛型
(1) 定义泛型

function log<T>(value: T): T { // 函数后面加入<T>,给输入参数value设置T类型,函数返回值类型也为T。
    console.log(value)
    return value;
}
log('d')

(2) 调用泛型
(a)调用时直接制定T的类型,将带有的地方,换成参数类型。\

    log<string[]>(['a', 'b', 'c'])

(b) 省略类型参数,利用类型推断。---推荐方式\

    log(['a', 'b', 'c'])

泛型函数

function setSex<T> (sex: T) {}
setSex<'男'>('女')

image.png

泛型接口

在定义接口时,为接口的属性或者方法定义泛型类型。在使用接口时,再指定具体的泛型类型

interface Log<T> {
    value: T
}
let myLog: Log<string> = {
    value: 'aa'
}
type Generics<T> = {
    name: string
    age: number
    sex: T
}

interface Generics<T> {
    name: string
    age: number
    sex: T
}

image.png

泛型类

class Log<T> {
    run (value: T) {
        console.log(value)
        return value;
    }
}
let log1 = new Log<number>(); 
log1.run(2)

let log2 = new Log(); // 没写类型的,log2可多中类型。
log2.run({});
log2.run('dd')

泛型约束: 对泛型进行一定的约束。

T必须满足extends的约束。

function log<T>(value: T): T {
    console.log(value, value.length) 
    return value;
}

定义一个log函数,打印值和值的length属性。但是value不一定有length属性。解决

interface Length {
    length: number
}
function log<T extends Length>(value: T): T {
    console.log(value, value.length)
    return value;
}
log<string[]>(['a', 'b', 'c']) // 数组有length属性,可以
log(['a', 'b', 'c'])
log(1) // 报错 因为1 number没有length属性

定义一个接口,里面有length属性,让T继承这个接口Length。
对T进行了约束,不再是随便了的,输入的类型必须具有length属性。

泛型参数的默认类型

在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。

当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。

泛型参数默认类型与普通函数默认值类似,对应的语法很简单,即 <T=Default Type> ,对应的使⽤示

例如下:

interface A<T = string> {
   name: T; 
}
const strA: A = { 
   name: "Semlinker" 
};
const numB: A<number> = {
   name: 101 
};