乐趣区

关于泛型:TypeScript之泛型

根底阐明

如果咱们须要定义一个函数,一个入参和一个返回值,入参和返回值类型须要保持一致,怎么办?

比方规定类型都是字符串,那么:

function doit(arg: string): string {return arg;}

能够看进去,类型这里写死成 string 了,那类型可不可以像参数一样定义成变量传递进来?当然能够,咱们革新一下代码:

function doit<T>(arg: T): T {return arg;}

这里通过 <T> 定义了一个类型变量 T,而这个 T 具体是什么类型,应用的时候用户传递即可:

let result: string = doit<string>("我是一个字符串");

事实上,编译器通过查看 arg 的值的类型,能够推断出 T 示意什么类型,因而,大部分状况下,上述代码能够简化一下:

let result: string = doit("我是一个字符串");

泛型类型

function doit<T>(arg: T): T {return arg;}

let myDoit: Function = doit;

咱们想把函数 doit 赋值给变量 myDoit,咱们定义 myDoit 的类型是 Function,那么,可不可以明确一下 myDoit 的类型细节?答案是必定的:

let myDoit: <T>(arg: T) => T = doit;

let myDoit: {<T>(arg: T): T } = doit;

泛型接口

聪慧的是必定能够想到,咱们还能够定义一个接口:

interface DoitFnType {<T>(arg: T): T;
}
    
let myDoit: DoitFnType = doit;

类型锁定

当初有一个状况,咱们在给 myDoit 赋值的是,曾经明确了类型 T 的理论值肯定是 string,那么,就能够这样改变:

interface DoitFnType<T> {(arg: T): T;
}
    
let myDoit: DoitFnType<string> = doit;

泛型类

也非常简单,咱们间接举个例子:

class Dog<T>{
    info: T;
    setInfo(info: T): void {this.info = info;}
}

创立的时候也是相似的:

let dog = new Dog<string>();

那么,setInfo 函数就只能传递字符串类型:

dog.setInfo('小狗🐶');

而上面的写法就是谬误的:

// Argument of type 'boolean' is not assignable to parameter of type 'string'.    
dog.setInfo(true);

舒适提醒:类的动态属性不能应用这个泛型类型,为什么?因为类型值是 new 的时候设置的,动态的时候基本不存在。

泛型束缚

function doit<T>(arg: T) {

    // Property 'length' does not exist on type 'T'.
    console.log(arg.length);
}

在下面的代码中,咱们心愿打印 arg 的属性 length,尽管类型 T 待定,可是咱们明确晓得传递的数据肯定会有 length 属性。可是,编译器并不能证实类型 T 蕴含 lenght 属性,因而会提醒谬误。

怎么办?咱们把代码革新一下:

interface ArgType {length: number;}

function doit<T extends ArgType>(arg: T) {console.log(arg.length);
}

当初这个泛型被束缚了,传递的参数必须蕴含 length 属性,比方字符串是能够的:

doit("小花");

而数字就不行:

// Argument of type 'number' is not assignable to parameter of type 'ArgType'.
doit(10);
退出移动版