泛型

108 阅读2分钟

可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件

基本概念

现在有个函数返回传入参数本身

function test(x:number):number{
    return x
}
console.log(test(1))  //1

那假如我想给他传入string类型的我们可能需要重新定义一个函数

function test(x:string):string{
    return x
}
console.log(test('test'))  //test

这样下去函数的复用性就变得很差,我们可以使用泛型来做改造

function test<T>(x:T):T{
    return x
}

console.log(test<number>(1))  //1
console.log(test<string>('test'))  //test

这样我们就可以在调用的时候手动指定类型来达到复用的效果

泛型类型

我们可以使用接口来接受一个泛型,下面继续改造一下上面的例子

interface testFace<T> {
    (arg: T): T;
}

let myTest: testFace<number>=x=>x;
console.log(myTest(1))  //1
泛型类

我们同样可以使用泛型来约束类

class Test<T> {
    num: T;
    constructor(num: T){
        this.num=num
    }
    add(x: T): T {
        return x;
    }
}

console.log(new Test<number>(1).add(1))
泛型约束

我们把最开始的例子加一个需求,我们需要在函数里面拿到传入参数的length属性

function test<T>(x:T):T{
    console.log(x.length) //类型T上不存在length属性
    return x
}

test<string>('test')

虽然我们传入了string类型是有length属性的,但是编译器并不能证明每种类型都有length属性,所以就报错了。

interface testFace{
    length:number
}

function test<T extends testFace>(x:T):T{
    console.log(x.length)
    return x
}
test<string>('test')

在上面的例子上我们声明了一个类型里面有length属性并且让类型T继承了该属性,解决了问题

函数参数使用类
class test{}

function create<T>(c: {new(): T}): T {
    return new c();
}
create(test)

或者说

class test{}

interface testFace<T>{
    new():T
}

function create<T>(c: testFace<T>): T {
    return new c();
}
create(test)