相关问题
HarmonyOS jsBridge 最佳实践
147浏览 • 1回复 待解决
ArkTS警告处理最佳实践(ArkTS-no-definite-assignment)
701浏览 • 1回复 待解决
HarmonyOS ArkTS中如何实现泛型构造函数
346浏览 • 1回复 待解决
网络监听的最佳实践有哪些?
361浏览 • 1回复 待解决
应用内整体换肤的最佳实践
267浏览 • 1回复 待解决
web写入customUseragent最佳实践
109浏览 • 1回复 待解决
HarmonyOS 沉浸式状态栏最佳实践
208浏览 • 1回复 待解决
分组列表最佳实践,希望提供一个完善的分组列表最佳实践。
787浏览 • 1回复 待解决
泛型参数转换为Object编译失败
572浏览 • 1回复 待解决
输出静态库的最佳实践
32浏览 • 1回复 待解决
HarmonyOS NEXT中ArkTS与Java/Kotlin的混合开发如何最佳实践?
499浏览 • 0回复 待解决
视频和直播播放HarmonyOS最佳实践
543浏览 • 1回复 待解决
组件是否支持泛型,想在自定义组件上使用泛型如struct CustomLayout<T> ,发现出现编译报错 。
801浏览 • 1回复 待解决
HarmonyOS 单列和瀑布流的最佳实践
96浏览 • 1回复 待解决
APP内整体置灰的最佳实践
178浏览 • 1回复 待解决
HarmonyOS公共UI组件库的最佳实践能提供吗?
229浏览 • 1回复 待解决
咨询JS库HarmonyOS化最佳实践和具体指导
47浏览 • 1回复 待解决
HarmonyOS 项目中大量图片资源存放位置最佳实践
685浏览 • 1回复 待解决
如何实现ArkTS高性能编程?
373浏览 • 1回复 待解决
HarmonyOS泛型类的属性如何初始化?
355浏览 • 1回复 待解决
HarmonyOS 点击埋点和曝光埋点的最佳实践是什么?
403浏览 • 1回复 待解决
是否有组件的统一依赖管理最佳实践?
30浏览 • 1回复 待解决
HarmonyOS 请提供框架层的最佳实践代码demo
19浏览 • 0回复 待解决
ArkTS 的异步编程模型是如何实现的?
56浏览 • 0回复 待解决
一:什么是泛型
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而是
在使用的时候再指定类型的一种特性
泛型 ---> 广泛的类型
二:泛型的好处
1.
代码复用性
组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型。
不同的类型处理逻辑可以复用同一段代码,而不用复制粘贴
2.
类型安全性(与any的区别)
设计泛型的关键目的是在
成员之间提供有意义的约束,这些成员可以是:类的实例成员、类的方法、函数参数和函数返回值。
泛型能帮助我们在灵活适用不同类型的同时,不丢失必要的类型约束。
三:泛型的语法
对于刚接触 TypeScript 泛型的读者来说,首次看到 <T> 语法会感到陌生。但这没什么可担心的,
就像传递参数一样,我们传递了我们想要用于特定函数调用的类型。
参考上面的图片,当我们调用 identity<Number>(1) ,
Number 类型就像参数 1 一样,它将在出现 T 的任何位置填充该类型。图中 <T> 内部的 T 被称为类型变量,它是我们希望传递给 identity 函数的类型占位符,同时它被分配给 value 参数用来代替它的类型:此时 T 充当的是类型,而不是特定的 Number 类型。
其中 T 代表
Type,在定义泛型时通常用作第一个类型变量名称。但
实际上 T 可以用任何有效名称代替。除了 T 之外,以下是常见泛型变量代表的意思:
其实并不是只能定义一个类型变量,我们可以引入希望定义的任何数量的类型变量。比如我们引入一个新的类型变量 U,用于扩展我们定义的 identity 函数:
除了为类型变量显式设定值之外,一种更常见的做法是
使编译器自动选择这些类型,从而使代码更简洁。我们可以完全省略尖括号,比如:
对于上述代码,编译器足够聪明,能够知道我们的参数类型,并将它们赋值给 T 和 U,而不需要开发人员显式指定它们。
在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推断出类型时,这个默认类型就会起作用。
泛型参数默认类型与普通函数默认值类似,对应的语法很简单,即 <T=Default Type>,对应的使用示例如下:
四:整改示例
1. 使用泛型解决参数类型不确定的 any 问题
这段代码用于修改数组元素的结构,使之附带索引值。为了适用于不同类型的数组,原来使用了 any。但这样就丢失了类型约束,比如我们传入 number 类型的数组,返回数组的元素类型变为 string,也不会收到报错提示。
基于我们这段代码的逻辑,我们实际的需求是返回数组元素的类型跟输入数组元素的类型一定是相同,只是元素的结构变化了。
为了达到这一约束,我们可以通过泛型改造如下:
1) 我们首先为新的元素结构定义一个新的 interface,因为这个结构也是类型无关的,所以也可以用到泛型
这个 interface 表示我们的类型可能带有 number类型的索引,以及字段名为 item 的值字段,其类型待确定。只需要加入 ? 可选标识是为了适配空数组的情况
2) 基于 IndexedItem 改造 getArray 方法
2. 多泛型参数与 extend
这里有2个问题:
1) 这里涉及多个 any 参数,查询入参 actionData 与结果回调里的 result 明显是无关的两个类型,所以我们需要分别指定泛型参数
2) queryPage 方法里,我们会给 actionData 设置 page 跟 limit 属性,但泛型类型是待定的任意类型,我们怎么要求它支持 page 跟 limit 呢? 这就是 extends 这个关键字的作用,我们在申明 actionData 的类型时,就申明了它应该满足的约束条件,具体看下面的泛型改造代码
有时候,我们希望类型变量对应的类型上存在某些属性。这时,除非我们显式地将特定属性定义为类型变量,否则编译器不会知道它们的存在。
一个很好的例子是在处理字符串或数组时,我们会假设 length 属性是可用的。让我们再次使用 identity 函数并尝试输出参数的长度:
在这种情况下,编译器将不会知道 T 确实含有 length 属性,尤其是在可以将任何类型赋给类型变量 T 的情况下。我们需要做的就是让类型变量 extends 一个含有我们所需属性的接口,比如这样:
T extends Length 用于告诉编译器,我们支持已经实现 Length 接口的任何类型。之后,当我们使用不含有 length 属性的对象作为参数调用 identity 函数时,TypeScript 会提示相关的错误信息:
3. 检查对象上的键是否存在
泛型约束的另一个常见的使用场景就是检查对象上的键是否存在。不过在看具体示例之前,我们得来了解一下 keyof 操作符,
keyof 操作符是在 TypeScript 2.1 版本引入的,该操作符可以用于获取某种类型的所有键,其返回类型是联合类型。"耳听为虚,眼见为实",我们来举个 keyof 的使用示例:
通过 keyof 操作符,我们就可以获取指定类型的所有键,之后我们就可以结合前面介绍的 extends 约束,即限制输入的属性名包含在 keyof 返回的联合类型中。具体的使用方式如下:
在以上的 getProperty 函数中,我们通过 K extends keyof T 确保参数 key 一定是对象中含有的键,这样就不会发生运行时错误。这是一个类型安全的解决方案,与简单调用 let value = obj[key]; 不同。
下面我们来看一下如何使用 getProperty 函数:
在以上示例中,对于 getProperty(tsInfo, 'superset_of') 这个表达式,TypeScript 编译器会提示以下错误信息:
很明显通过使用泛型约束,在编译阶段我们就可以提前发现错误,大大提高了程序的健壮性和稳定性。