泛型允许同一个函数或类支持多种数据类型,极大提升了代码的灵活性和复用性

泛型之前

  1. // 函数重载
  2. function log(value: string): string;
  3. function log(value: number): number;
  4. function log(value: string[]): string[];
  5. function log(value: any) {
  6. return value;
  7. }
  8. // 联合类型
  9. function log(value: string | number | string[]): string | number | string[] {
  10. return value;
  11. }
  12. // any类型
  13. function log(value: any) {
  14. return value;
  15. }

使用泛型

不预先确定的类型,具体类型在使用时才能确定 优势: 类型T不需要预先指定,相当于any,保证输入参数和返回值的一致性 定义方式: 未知类型使用表示,参数类型,返回值类型均为T

泛型声明

  1. function log<T>(value: T): T{
  2. return value
  3. }

泛型调用

  1. // 1.直接指定T的具体类型进行调用
  2. log<string[]>(["a", "b"]);
  3. // 2.利用TS类型推断,省略类型参数
  4. log(["a", "b"]);

使用泛型定义函数类型

泛型不仅可以定义函数,还可以定义函数类型 定义方式: 类型别名type关键字 + 名称,可定义一个泛型函数类型

  1. // 泛型声明
  2. function log<T>(value: T): T {
  3. return value;
  4. }
  5. // 使用泛型定义函数类型Log
  6. type Log = <T>(value: T) => T;
  7. // 声明变量myLog为Log类型
  8. let myLog: Log = log;

泛型接口

泛型也可以用于接口中,对接口中的函数或成员进行约束 使用泛型约束接口中的函数:和类型别名的定义方式是完全等价的。仅仅约束了一个函数

  1. // 使用泛型约束接口中的函数
  2. interface Log {
  3. <T>(value: T): T;
  4. }

还可以使用泛型来约束接口的其他成员 注意:当泛型变量约束了整个接口后,实现时必须指定一个具体类型

  1. interface ResponseData<T> {
  2. resCode: number;
  3. resData: T;
  4. message: string;
  5. }
  6. let arrayResult: ResponseData<string[]> = {
  7. resCode: 0,
  8. resData: ["1", "2"],
  9. message: "",
  10. };

使用泛型约束类的成员

定义一个泛型类,将泛型变量放在类名称之后,就可以约束类的所有成员

  1. // 泛型类-约束所有类的成员了
  2. class Log<T> {
  3. run(value: T) {
  4. return value;
  5. }
  6. }
  7. // 实例化类时,如果指定T的类型,则只能传入指定类型
  8. let log = new Log<number>();
  9. log.run(1);
  10. // 如果不指定T的类型,则可以传入所有类型
  11. let log = new Log();
  12. log.run("test Log");

注:泛型不能用于类的静态成员

image.png

泛型约束

使用泛型的情况下,如果需要对T.length进行输出,则错误提示:

image.png

改进: 由于T继承了Length接口,所以类型检查不再报错 但此时T也受到了一定约束,要求必须是具length属性。如数、字符串、对象等

  1. // 定义length属性接口
  2. interface Length {
  3. length: number;
  4. }
  5. // 类型T继承Length接口
  6. function log<T extends Length>(value: T): T {
  7. console.log(value.length);
  8. return value;
  9. }

泛型的好处

函数和类可以轻松地支持多种类型,增强程序的控制性 不必写多余函数重载,冗长的联合类型声明,增强代码可读性 灵活控制类型之间的约束

  1. class DLog<T> {
  2. run(value: T) {
  3. console.log(value);
  4. return value;
  5. }
  6. }
  7. let log1 = new DLog<number>();
  8. log1.run(1);
  9. // log1.run('1')
  10. let log2 = new DLog();
  11. log2.run({ a: 1 });
  12. log2.run("1");
  13. interface Length {
  14. length: number;
  15. }
  16. function Dlog<T extends Length>(value: T): T {
  17. console.log(value, value.length);
  18. return value;
  19. }
  20. Dlog([1]);
  21. Dlog("123");
  22. Dlog({ length: 1 });

学习笔记出自于梁宵老师课程