基础说明
如果我们需要定义一个函数,一个入参和一个返回值,入参和返回值类型需要保持一致,怎么办?
比如规定类型都是字符串,那么:
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);
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。