前言:泛型是语言的一种特性。

泛型是一种参数化的设计。我们都知道声明函数时参数叫做形参,而真正调用的时候是实参。对于泛型来说,就是将类型变为一个类型变量,在调用的时候传入具体的类型作为参数。泛型的数据类型是根据传入的实参来确定。

泛型变量

一般可以 T K U 表示,但也可以用其他大写字母表示泛型。

放在 <> 里,表示泛型变量,可以是一个,也可以是多个。

1
function echo<T>(param:T):T {};

泛型的使用

泛型可以在类,接口,方法中使用。

1
2
3
4
5
6
7
8
9
10
11
泛型不仅是可以在函数中使用,也可以在类 和 接口中使用。

class Person<T> {
type: T;
name: string;
constructor(name?: string) {
this.name = name;
}
}

// class 是实际的类型,接口是虚拟的类型,对于真实世界的JS 来说

泛型约束 extends

通过extends 关键字,泛型类型可以约束。

1
2
3
4
5
6
7
8
9
10
11
12
interface Person1<T extends string | number> { 
// ^__ 这里 泛型变量 T 约束为 string 和 number
type: T;
name: string;
}
type Student = {
name: string;
age: number;
};

let stu1: Person1<1>;
stu1.type.toFixed(2); // ok
  • 约束为keyof
1
2
3
4
5
6
7
8
9
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a");
getProperty(x, "m");
// ^__ [ts] 类型“"m"”的参数不能赋给类型“"a" | "b" | "c" | "d"”的参数。

类型索引(Type Index)

1
2
3
4
5
6
7
8
9

01 //索引类型(Index types)
02 function getProperty<T,K extends keyof T>(obj: T, key: K) {
03 return obj[key];
04 }
05 let obj = { a: 1, b: 2, c: 3, d: 4 };
06 let x = getProperty(obj, "a"); // 1
07 let m =getProperty(obj, "m"); // 错误
// [ts] 类型“"m"”的参数不能赋给类型“"a" | "b" | "c" | "d"”的参数。