初识泛型
如果我们想写一个函数,它的参数和返回值类型相同,首先我们会想到下面这种写法:
function getNum(num: number): number{
return num;
}
function getStr(str: string): string{
return str;
}
或者使用any
来定义类型:
function getItem(arg: any): any{
return arg;
}
但是使用any
类型会导致我们无法保证参数类型与返回的类型一定是相同的。所以我们可以采用下面这种方式:
function identity<T>(arg: T): T{
return arg;
}
我们在函数名称后面声明变量<T>
,它用于捕获开发者传入的参数类型,然后我们就可以使用T做参数类型和返回值类型了。
泛型变量
现在假设我们想操作T
类型的数组而不直接是T
:
function getArr<T>(arg: T[]): T[]{
return arg;
}
console.log(getArr([1,2])); //[1,2]
这里我们传入的是数字数组,将返回一个数字数组,因为此时T
的的类型为number
。 这时我们把泛型变量T
当做类型的一部分使用,而不是整个类型。
泛型接口
interface GenericFn<T>{
(arg: T): T
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericFn<number> = identity;
// let myIdentity: GenericFn<number> = num=>num;
泛型类
class MyArr<T> {
arr: T[] = [];
push(num: T) {
this.arr.push(num)
}
}
let a = new MyArr<number>();
a.push(10);
泛型约束
type Params = number | undefined;
class MyArr<T extends Params> {
arr: T[] = [];
push(num: T) {
this.arr.push(num)
}
}
let a1 = new MyArr<number>();
let a2= new MyArr<string>(); //类型“string”不满足约束“Params”
索引类型
function getValue(obj: object, key: string) {
return obj[key]
}
function getValue<T extends object, U extends keyof T>(obj: T, key: U) {
return obj[key];
}
我们用索引类型keyof T
把传入的对象的属性类型取出生成一个联合类型,这里的泛型 U
被约束在这个联合类型中。