TypeScript实战-11-泛型

一,前言

TS为ES新增了一个面向对象语言的重要概念:泛型
泛型允许同一个函数或类支持多种数据类型,极大提升了代码的灵活性和复用性

二,泛型之前

一个可以打印多种数据类型的log函数
方法1:函数重载
// 函数重载
function log(value: string): string;
function log(value: number): number;
function log(value: string[]): string[];
function log(value: any) {
    return value
}
方法2:联合类型
// 联合类型
function log(value: string | number | string[]): string | number | string[] {
    return value
}
方法3:any类型
使用any类型会失去类型间的约束关系,忽略输入参数类型和函数返回值类型必须一致
// any类型
function log(value: any) {
    return value
}

三,泛型

不预先确定的类型,具体类型在使用时才能确定
泛型的优势:
类型T不需要预先指定,相当于any,保证输入参数和返回值的一致性
定义方式:
未知类型使用<T>表示,参数类型,返回值类型均为T
泛型声明:
function log<T>(value: T): T{
    return value
}
泛型调用:

1,直接指定T的具体类型进行调用

// 1,直接指定T的具体类型进行调用
log<string[]>(['a', 'b'])

2,利用TS类型推断,省略类型参数

// 2,利用TS类型推断,省略类型参数
log(['a', 'b'])

三,使用泛型定义函数类型

泛型不仅可以定义函数,还可以定义函数类型

定义方式:

类型别名type关键字 + 名称,可定义一个泛型函数类型

使用泛型定义函数类型:

// 泛型声明
function log<T>(value: T): T{
    return value
}

// 使用泛型定义函数类型Log
type Log = <T>(value: T) => T

// 声明变量myLog为Log类型
let myLog: Log = log

四,泛型接口

泛型也可以用于接口中,对接口中的函数或成员进行约束

使用泛型约束接口中的函数:

和类型别名的定义方式是完全等价的,仅仅约束了一个函数
// 使用泛型约束接口中的函数
interface Log {
    <T>(value: T): T
}

还可以使用泛型来约束接口的其他成员:

例如介绍接口时使用的Response例子,使用泛型进行修改
// API协议约定返回格式-resData为可变类型
interface ResponseData<T> {
    resCode: number;
    resData: T
    message: string;
}

注意:

当泛型变量约束了整个接口后,实现时必须指定一个具体类型

这样就增强了协议模板对象的复用性,可用于接收所有后台数据格式,如返回string数组

let arrayResult: ResponseData<string[]> = {
    resCode: 0,
    resData:['1','2'],
    message: "",
}

五,使用泛型约束类的成员

定义一个泛型类,将泛型变量放在类名称之后,就可以约束类的所有成员
// 泛型类-约束所有类的成员了
class Log<T> {
    run(value: T) {
        return value
    }
}

实例化类时,如果指定T的类型,则只能传入指定类型

// 实例化类时,如果指定T的类型,则只能传入指定类型
let log = new Log<number>()
log.run(1)

如果不指定T的类型,则可以传入所有类型

// 如果不指定T的类型,则可以传入所有类型
let log = new Log()
log.run("test Log")
注意:泛型不能用于类的静态成员

使用泛型约束类的static成员


六,泛型约束

在使用泛型的情况下,如果需要对T.length进行输出,会提示错误:
泛型约束
由于T的具体类型未知,所以提示T类型上不存在length属性

这时可以使用类型约束:

预先定义一个含有length属性的接口,让类型T继承这个接口
// 预先定义一个含有length属性的接口,
interface Length {
    length: number
}
// 让类型T继承这个接口
function log<T extends Length>(value: T): T {
    console.log(value.length)
    return value
}

由于T继承了Length接口,所以类型检查不再报错
但此时T也受到了一定约束,要求必须是具length属性,如数组,字符串,对象等


七,泛型的优势

泛型使函数和类可以支持多种类型,提升了代码的复用性和可扩展性

省去了函数重载和联合类型声明,增强了代码可读性

能够灵活控制类型间的约束关系

八,结尾

本篇介绍了TS泛型相关知识点,包括:

1,泛型的声明和实现
2,使用泛型定义函数类型
3,泛型接口
4,使用泛型约束类的成员
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BraveWangDev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值