泛型允许同一个函数或类支持多种数据类型,极大提升了代码的灵活性和复用性
泛型之前
typescript
// 函数重载
function log(value: string): string
function log(value: number): number
function log(value: string[]): string[]
function log(value: any) {
return value
}
// 联合类型
function log(value: string | number | string[]): string | number | string[] {
return value
}
// any类型
function log(value: any) {
return value
}
使用泛型
不预先确定的类型,具体类型在使用时才能确定 优势: 类型T不需要预先指定,相当于any,保证输入参数和返回值的一致性 定义方式: 未知类型使用
<T>
表示,参数类型,返回值类型均为T
泛型声明
typescript
function log<T>(value: T): T {
return value
}
泛型调用
typescript
// 1. 直接指定T的具体类型进行调用
log<string[]>(['a', 'b'])
// 2. 利用TS类型推断,省略类型参数
log(['a', 'b'])
使用泛型定义函数类型
泛型不仅可以定义函数,还可以定义函数类型 定义方式: 类型别名type关键字 + 名称,可定义一个泛型函数类型
typescript
// 泛型声明
function log<T>(value: T): T {
return value
}
// 使用泛型定义函数类型Log
type Log = <T>(value: T) => T
// 声明变量myLog为Log类型
let myLog: Log = log
泛型接口
泛型也可以用于接口中,对接口中的函数或成员进行约束 使用泛型约束接口中的函数:和类型别名的定义方式是完全等价的。仅仅约束了一个函数
typescript
// 使用泛型约束接口中的函数
interface Log {
<T>(value: T): T
}
还可以使用泛型来约束接口的其他成员 注意:当泛型变量约束了整个接口后,实现时必须指定一个具体类型
typescript
interface ResponseData<T> {
resCode: number
resData: T
message: string
}
let arrayResult: ResponseData<string[]> = {
resCode: 0,
resData: ['1', '2'],
message: '',
}
使用泛型约束类的成员
定义一个泛型类,将泛型变量放在类名称之后,就可以约束类的所有成员
typescript
// 泛型类-约束所有类的成员了
class Log<T> {
run(value: T) {
return value
}
}
// 实例化类时,如果指定T的类型,则只能传入指定类型
let log = new Log<number>()
log.run(1)
// 如果不指定T的类型,则可以传入所有类型
let log = new Log()
log.run('test Log')
注:泛型不能用于类的静态成员
泛型约束
使用泛型的情况下,如果需要对T.length进行输出,则错误提示:
改进: 由于T继承了Length接口,所以类型检查不再报错 但此时T也受到了一定约束,要求必须是具length属性。如数、字符串、对象等
typescript
// 定义length属性接口
interface Length {
length: number
}
// 类型T继承Length接口
function log<T extends Length>(value: T): T {
console.log(value.length)
return value
}
泛型的好处
函数和类可以轻松地支持多种类型,增强程序的控制性 不必写多余函数重载,冗长的联合类型声明,增强代码可读性 灵活控制类型之间的约束
typescript
class DLog<T> {
run(value: T) {
console.log(value)
return value
}
}
let log1 = new DLog<number>()
log1.run(1)
// log1.run('1')
let log2 = new DLog()
log2.run({ a: 1 })
log2.run('1')
interface Length {
length: number
}
function Dlog<T extends Length>(value: T): T {
console.log(value, value.length)
return value
}
Dlog([1])
Dlog('123')
Dlog({ length: 1 })