当前位置: 首页 > news >正文

TypeScript5-泛型

泛型是 TS 中一个重要的概念,它可以创建可复用的组件,同时保持对类型信息的一致性。

泛型提供了一种方式使得类型可以被参数化,这样就可以创建可以适用于各种数据类型的函数或类,而不仅仅限于一个数据类型。

一、泛型

先来看一个需求:

我有一个 compiler 函数,我希望这个函数可以接收一个字符串或一个字符串数组,返回值也是一个字符串或一个字符串数组,有什么办法?

结合多种编程语言,我们很容易想到几种解决方法:

1. 使用函数重载

在传统的面向对象编程语言中,例如 Java 或 C++,函数重载允许我们使用相同的函数名定义多个函数,只要它们的参数列表(参数的数量或类型)不同即可。在编译过程中,编译器会通过函数调用时的参数列表判断调用哪个重载函数。

在 JavaScript 中,如果尝试使用相同的函数名定义多个函数,后定义的函数将覆盖先定义的函数。

在 TS 中可以函数重载,如我们可以这样做:

function compliler(template: string): string;
function compliler(template: string[]): string[];
function compliler(template: any) {return template;
}
console.log(compliler('abc')); // "abc" 
console.log(compliler(['abc', 'efg'])); // ["abc", "efg"] 
// console.log(compliler(123)); // 报错

在这个例子中,compiler 函数有两个重载签名和一个实现函数。第一个重载签名接受一个字符串类型的参数,返回一个 字符串。第二个重载签名接受一个字符串数组类型的参数,返回一个字符串数组。

实现函数接受任意类型的参数,返回参数本身。这个实现函数必须能兼容所有的重载签名,所有对 compiler 函数的调用都会执行这个实现函数。

需要注意的是,TS 在解析函数重载时,会按照重载签名从上到下的顺序进行匹配,所以在编写重载签名时,应该把最精确的定义放在最前面。

使用这个方法可以解决这个需求,但是这么一个简单的需求,写出的代码看起来很麻烦,让人很不舒服,不够简洁,因此此方案作废。

2. 使用联合类型

使用联合类型也可以解决这个需求。

function compiler(template: string | string[]): string | string[] {return template;
}

我们定义了一个 compiler 函数,有一个字符串类型或字符串数组类型的参数,返回值可以是字符串,也可以是字符串数组。

这个方法和使用函数重载的方法相比,代码简洁了许多。但如果参数类型可以是很多种,比如 template 参数同时也可以是数字类型、布尔类型、数字数组等。虽然可以在参数的类型注解后面继续加上 | number | bool | number[],但这样代码的观感也不是很好。

在这个例子中,传入 compiler 函数的参数类型可以和返回值类型不一致。如果想让返回值的类型和参数的类型一致(如函数重载案例的效果),就可以使用类型变量。

3. 使用类型变量

类型变量是 TS 中的一种特殊的变量,只用于表示类型而不是值。通过使用类型变量,我们可以创建出在多种类型之间都可以共享的函数或组件。

// 类型变量
function compiler <T> (template: T): T {// ...return template;
}

尖括号中的 T 就是类型变量,它可以捕获用户传入的一些类型,允许我们跟踪函数中使用的这些类型的信息。这里我们定义了类型变量 T,就可以在函数定义中使用它。我们定义了参数 template 的类型为 T,返回值类型也为 T,这样就保证了参数类型和返回值类型一致。

在这个案例中,T 可以是任意类型,函数运行时也并不知道 T 是什么类型。、

为了解决这个问题,我们可以在调用函数时指定参数的类型。如下所示:

compiler<string>('123');

这里我们指定了传入的参数类型为字符串,后面传入的 '123' 就是一个字符串。

也可以直接传入 '123',TS 有类型推导机制,在编译时编译器会推导出传入的参数为字符串类型,T 这时也就是字符串类型,返回值的类型也自然就是字符串类型。

// 类型推导
compiler('123');

现在返回去看需求,传入的参数需要是字符串类型或字符串数组类型,我们就可以结合联合类型这样做:

compiler<string | string[]>('123');

这个案例中的 compiler 函数就是一个泛型函数。

二、泛型约束

来看下面的案例:

function compiler <T> (template: T): T {console.log(template.length);// ...return template;
}compiler<string>('123');

编辑器可以通过我们传入的参数 '123' 来推断出 T 为字符串类型,但是编译时仍然会报错:Property 'length' does not exist on type 'T'.,表示类型 T 中不存在 length 这个属性。

我们可以使用继承接口的方法来实现泛型约束,通过接口来指定一个泛型必须具有某些属性或方法。

interface Len {length: number;
}function compiler <T extends Len> (template: T): T {console.log(template.length);// ...return template;
}compiler<string>('123');

这里我们先定义一个接口 Len,接口中有一个属性 length,再让类型变量 T 继承这个接口,编译器知道了类型 T 下有 length 这个变量,即可编译成功。

这里需要注意,使用这种方法,我们传入的这个参数必须要有 length 这个属性,否则会报错。如:

compiler([]); // 0
compiler(false); // 报错

第一行我们传入一个数组,我们都知道,数组是有 length 属性的,因此可以正确运行,输出 0。

第二行我们传入一个 false,为布尔类型,布尔类型没有 length 属性,所以会报错:Argument of type 'boolean' is not assignable to parameter of type 'Len'.,表示布尔类型和接口 Len 不匹配。

如果我们修改 Len 接口,在接口中增加一个 split 属性,类型为 函数:

interface Len {length: number;split: Function;
}

修改 Len 接口后,传入 compiler 的参数必须同时具有 length 属性和 split 函数。因此 compiler([]) 会报错,因为数组不具备 split 方法。

三、总结

使用泛型的优势:

1. 函数和类可以轻松的支持多种类型,增强程序的扩展性。

2. 不必写多条函数重载、联合类型声明,增强代码的可读性。

3. 灵活控制类型之间的约束。

http://www.lryc.cn/news/68137.html

相关文章:

  • IMX6ULL裸机篇之DDR3的时钟配置
  • PBDB Data Service:Specimens and measurements(标本和测量)
  • Zookeeper(一)
  • Maven(五):Maven的使用——依赖的测试
  • 超级独角兽 Databricks 的崛起之路
  • python 3.8 + tensorflow 2.4.0 + cuda11.0 的问题
  • 华为杯”研究生数学建模竞赛2021 年中国研究生数学建模竞赛 E 题: 信号干扰下的超宽带(UWB)精确定位问题-参考思路
  • Java 中的访问修饰符有什么区别?
  • Go基础篇:接口
  • 边缘计算:数字时代的新战场
  • PBDB Data Service:Fossil occurrences(化石产出记录)
  • 虾皮Shopee商品详情接口(item_get-根据ID取商品详情)代码封装
  • 原生js手动实现一个多级树状菜单效果(高度可过渡变化) + 模拟el-menu组件实现(简单版)
  • RK3568平台开发系列讲解(Linux内存篇)Linux内存管理框架
  • 你的编程能力从什么时候开始突飞猛进?
  • 滨州高企认定条件
  • Azkaban学习——单机版安装与部署
  • table标签-移动端适配
  • Yolov8改进---注意力机制:DoubleAttention、SKAttention,SENet进阶版本
  • 【逆向工程核心原理:TLS回调函数】
  • “Shell“Awk命令
  • 射频放大器的原理和作用(射频放大器和功率放大器的区别)
  • 揭秘KubeEdge边缘网络项目EdgeMesh:如何打造高速、安全、低延迟的互联网连接
  • Java设计模式 14-访问者模式
  • 【数据结构】线性表之链表
  • 微服架构基础设施环境平台搭建 -(四)在Kubernetes集群基础上搭建Kubesphere平台
  • Linux开发板安装Python环境
  • ChatGPT 聊天接口API 使用
  • 软件测试月薪2万,需要技术达到什么水平?
  • 从入门到进阶,Vue框架让Web开发更简单高效