TypeScript 泛型|青训营

72 阅读2分钟

泛型

在定义一个不确定类型的变量时,有两种方式:
一种是使用any类型定义,但any存在一个问题,虽然已经指定传入值的类型是any,但是any是适用于JS的,这样会无法获取函数返回值的类型,且会失去TS类型保护。
另一种方式就是使用泛型,在定义函数、接口、类型时,不预先指定具体类型,而是在使用时再指定类型。

泛型出现在尖括号<>的ts代码中,其中T表示传入的类型。
T以与函数中参数相同的方式运行,作为声明的类型的占位符。多个泛型类型也可以出现在单个定义中,例如<T,K,V>

常见泛型变量代表的意思:

  • T(Type):类型
  • K(Key):键
  • V(Value):值
  • E(Element):元素

泛型可以在函数、类型、类和接口中使用。

以下是使用泛型的函数示例:

function identity<T> (value: T):T {
    return value;
}
console.log(identity<Number>(1)); //返回的是number类型的1
console.log(identity<string | boolean>(true)); //返回布尔类型的true
console.log(identity<string | boolean>('1')); //返回string类型的1

tips: 当返回值中可能为空或者有不同类型的值时,可以用 | 来定义不同的类型。

定义identity函数时用泛型约束参数和返回值为T,这里的T是占位的作用,在调用identity<Number>(1)时,Number类型像参数1一样,它会在调用函数时替代T的位置

不使用泛型的话,函数定义应该是这样的:

function identity (value: Number):Number {
    return value;
}
console.log(identity(1))

但这种方法没有泛型灵活,若我想再定义上面类似的函数,但要求入参和返回值为String,那么就需要再写一个函数。

function identity (value:String):String {
    return value;
}
console.log(identity(1))

而使用泛型只需在调用函数时指定String类型便可以

function identity<T> (value: T):T {
    return value;
}
console.log(identity<String>(1))

泛型约束

泛型变量T(Type)可以是任意类型,但这也导致无法访问任何属性

function identity<T> (value: T):T {
    console.log(value.length)
    return value;
}
identity<String>('a')

在代码 console.log(value.length)中会进行报错,“类型‘Type’上不存在属性‘length’”。因为并不是所有的类型都具有length属性的。此时,可以通过泛型约束对参数添加约束来解决。

  1. 先创建一个接口,该接口提供length属性
    interface ILength { length: number}
  2. 创建泛型类型接口实例
    type length = { length: number}
  3. 通过继承extends使用该接口,添加约束
function identity<T extends Length> (value: T):T {
    console.log(value.length)
    return value;
}

添加该约束后,传入的类型要求具备length属性