TS中的泛型

TS中的泛型

typescript 中 最难的无疑是泛型(Generices), 那么泛型出现的动机是什么呢?

思考一个问题: 泛型是怎样出现的,它要解决那些问题?

现在有一个 echo 方法,传入什么类型的值返回什么类型的值

function echo(arg) {
    return arg
}
const result = echo(123)

result 返回值是一个 any 类型, 这不符合我们的预期, 那么指定入参和出参的类型,同样不符合预期, 这时候就用到泛型了

泛型(Generices)

定义

  • 定义函数,接口或类时,不预先指定具体类型,而是在使用的时候指定具体类型

使用

  • 在函数名称后面加一对尖括号,尖括号里面泛型名称(习惯写法为T,可以是任意名字),
  • 泛型名称可以看成是一个变量(也可以看作是一个占位符)
  • 泛型可以是任意类型在使用时指定即可
// 函数名后面插入尖括号,写入泛型名称T,参数和返回类型都是T
function echo<T>(arg:T):T {
    return arg
}
const str: string = '字符串'
// result 是 string 类型
const result = echo(str)
// 也可以不指定类型, ts 可以自动推断出类型
const result = echo(123) // 此时 result 为 number 类型

现在有个元组,里面有两个不同类型的值, 把这个元组传入 swap 方法中, 交换两个值的位置, 返回交换位置后的元组

// 根据上面需求我们实现下

// 定义元组
const tuple:[number,string] = [123,'str']

// swap 方法实现
function swap<T,U>(tuple:[T,U]):[U,T] {
    return [tuple[1],tuple[0]]
}

// 调用
const result = swap(tuple)

result[0]. 可以调用 字符串 的方法

result[1]. 可以调用 number 的方法

约束泛型

下面这个方法, 输出arg.length length下面有波浪线,出现了错误

下图提示: 泛型 T 不一定包含属性 length, 所以静态类型检查就会报错


那么这个函数接受的参数应该是有length属性的参数,使用 extends 关键字约束传入的泛型

使用 extends 使传入值满足约束条件

// 首先定义一个 IWithLength 的 interface
interface IWithLength {
    length: number
}
// 在 泛型名称T后面 使用 extends 关键字继承定义的 IWithLength 接口
function echoWithLength<T extends IWithLength>(arg:T):T {
    console.log(arg.length)
    return arg
}
// 验证下
const str = echoWithLength(`str`)
const obj = echoWithLength({a:1,b:'str'})
const arr = echoWithLength([1,2,3])

使用泛型描述类

新建一个队列类上实现两个方法,进入队列,离开队列, 这时候就可以使用泛型类

// 类名称后面传入泛型
class Queue <T>{
    private data:T[] = [];
    push(item:T) {
        return this.data.push(item)
    } 
    pop():T {
        this.data.shift()
    }
}
// 实例化 的时候传入想要的类型
const queue1 = new Queue<number>()
queue1.push(1)
console.log(queue1.pop().toFixed()) // 这里返回类型就是number可以使用 number 方法

// 实例化 的时候传入想要的类型
const queue2 = new Queue<string>()
queue1.push(`str`)
console.log(queue2.pop().length) // 这时可以调用 string 的方法

使用泛型描述对象

// 定义类型的时候 动态指定值 
interface KeyPair<T,U> {
    key: T;
    value: U;
}

let kp1: KeyPair<number,string> = { key: 123, value: 'str' }
let kp2: keypair<string,number> = { key: 'str', value: 123 }

使用泛型描述数组

定义一个number类型的数组

// 方法一
let arr2: Array<number> = [1,2,3]

// 方法二
interface Info {
    age: number
    name: string
}
let arr1: Info[] = [
    {age: 18, name: 'lili'},
    {age: 10, name: 'hihi'},
]

使用泛型描述函数

// 定义一个泛型接口
interface IPlus<T> {
    (a:T,b:T) : T
}
// 变量绑定类型
const plus: Iplus<number> = function (a,b){
    return a + b;
}
// number 类型
const a:Iplus<number> = plus(1,2)
// string 类型
const b:IPlus<string> = plus('hello','wold')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。