【Typescript】泛型函数,泛型接口,泛型类,泛型约束,9

目录

泛型就是不预先确定的数据类型,具体的类型在使用的时候才能确定。

我们通常有泛型参数,泛型函数,泛型接口,泛型类等。

泛型参数

泛型参数与函数的参数等同对待,它只不过是另一个维度的参数,是代表类型,而不是代表有值的参数。泛型在高级类型中有广泛的应用。

首先我们来看一个函数:

function log(value: string): string {
    console.log(value);
    return value;
}

如果打印的value是个数组类型,前面介绍过,我们就需要用函数重载的方法:

function log(value: string): string;
function log(value: string[]): string[];
function log(value: any): any {
    console.log(value);
    return value;
}

当然也可以用联合类型:

function log(value: string | string[]): string | string[] {
    console.log(value);
        return value;
}

还有any类型:

function log(value: any): any {
    console.log(value);
    return value;
}

any类型没有输入参数的约束限制。这里就需要泛型。

我们用泛型来 改造我们的log函数。

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

log<string[]>(['a', 'b']);
log(['a', 'b']); // 这种是比较推荐的方式

泛型函数

不仅可以用泛型来定义函数参数,也可以定义函数类型。下面来看一个泛型函数的实现。

function log<T>(value: T): T {
    console.log(value);
    return value;
}
type Log = <T>(value: T) => T 
let myLog: Log = log;

泛型接口

function log<T>(value: T): T {
    console.log(value);
    return value;
}
interface Log<T> {
    (value: T): T
}
let myLog: Log<number> = log;
myLog(1);

如果不指定类型,我们也可以在接口的定义中指定一个默认的类型。

function log<T>(value: T): T {
    console.log(value);
    return value;
}
interface Log<T = string> {
    (value: T): T
}
let myLog: Log = log;
myLog('1'); // 这里myLog的参数就默认为string类型了。

泛型类

与泛型接口非常类似,泛型也可以约束类的成员, 泛型不能应用于类的静态成员中。

class Log<T> {
    run (value: T) {
        console.log(value);
        return value;
    }
}

let log1 = new Log<number>();
log1.run(1);
let log2 = new Log();
log2.run('2');
log2.run(2);

泛型约束

class Log<T> {
    run (value: T) {
        console.log(value, value.length); // Property 'length' does not exist on type 'T'.
        return value;
    }
}


这个时候就需要用到类型约束这个概念。

interface Length {
    length: number
}
function log<T extends Length>(value: T): T {
    console.log(value, value.length); // Property 'length' does not exist on type 'T'.
    return value;
}

log([1]);
log('123');
log({length: 1});

这样我们就能通过类型检查。T继承了length接口,这表示T受到了一些的约束,就不再是任意类型都可以传了。输入的参数不管是什么类型,但是必须有length属性。

使用泛型的好处

1、函数和类可以轻松的支持多种类型,增强程序的扩展性。

2、不必写多条函数重载,冗长的联合类型声明,增强代码可读性。

3、灵活控制类型之间的约束。