网易首页 > 网易号 > 正文 申请入驻

从 React 源码的类型定义中,我学到了什么?

0
分享至

作者:神说要有光

React 类型定义做的挺完善的,考虑到了各种类型的处理,也考虑到了低版本的兼容,从中还是能学到不少东西的。

今天看了下 React 的类型定义,也就是 @types/react 包下的 index.d.ts,发现了一些有趣的写法。

这篇文章就分享下这些写法,估计大部分人都不知道:

提取可选索引的值

首先,我看到了这样一段类型逻辑:

这段逻辑就是取索引类型的 ref 索引的值,但是是通过模式匹配的方式,把提取的类型放到 infer 声明的局部变量 R 里返回的。

简化一下就是这样的:

提取 Props 的 ref 索引的值的类型返回。

我在想,这么麻烦干什么,直接 Props['ref'] 不就能拿到 ref 索引的值么?

于是我就改成了这样:

然后试了下:

不对呀,人家这是可选索引,值的类型是包含 undefined 的联合类型。

那就 Exclude 下不就行了:

这样也比那个 infer 的方式简洁呀,为啥 React 类型定义都是用的 infer 取的可选索引的类型呢?

后来我突然想到,如果这个 ref 值的类型就是 undefined 呢?

我试了下:

确实,我那样写是有问题的,如果值的类型本来就是 undefined,Exclude 掉 undefined 后就是 never 了,而人家那种方式就没问题:

于是我就加一下 undefined 的处理:

这样就行了。

对比了下两种写法:

确实还是 React 的那种写法更简洁。

对了,那上面那层判断呢?

这个判断没必要的吧,如果没有 ref,那 Props['ref'] 不就是返回 never 么,没必要单独判断呀?

然后我就看到了这样一段注释:

在 ts 3.0 中,如果索引类型没有对应的索引,那返回的类型是 {} 而不是 never。

原来如此,这个 'ref' extends keyof Props 是为了做兼容的呀,不是没意义。

这就是我从这个类型中学到的两个知识点:

  • 索引访问 Obj[Key] 和 infer 提取和都可以取到索引类型的某个索引的值,但是当处理可选索引的时候,用 infer 更简洁一些,因为前者要取出类型之后再单独处理下 undefined,而后者在 infer 的时候就顺便处理了 undefined。
  • ts 3.0 中如果索引类型没有对应的索引,返回的是 {} 不是 never,如果对兼容性要求高的话,可以用 'xx' in keyOf Obj 的方式做下兼容。

我们从这个类型里学到了不少东西,再来看下第二个类型:

索引类型和 any、never 的处理

然后我又看到了这样一个类型,

先试一下它的功能,传入两个索引类型:

看下结果:

这是些啥啊,谁能看得懂呀。

其实这只是因为 TS 没有计算出最终的类型而已,用到的时候才会计算,所以我们可以这样处理下:

Copy 的高级类型是通过映射类型的语法构造了一个新的索引类型,它的功能是原封不动的复制一个索引类型。

类型参数 Obj 约束为索引类型,也就是 Record。key 保持不变,也就是 Key in keyof Obj,value 也保持不变,也就是 Obj[Key]。

因为重新生成的类型的过程中要做计算,所以那个类型就能提示出最终的结果了:

所以说,这个类型的作用是两个索引类型 A,B,只有 A 中有的就保留,A、B 都有的变为可选,B 有但 A 没有的变为可选。

那这段逻辑具体是怎么用 TS 实现的呢?

我们先来过一下 TS 这些内置的高级类型:

Pick

Pick 的作用是通过映射类型的语法构造一个新的索引类型,根据传入的 Key 对索引做下过滤:

type Pick

= { [P in K]: T[P]; };1.

测试下:

Partial

Partial 也是通过映射类型的语法构造一个新的索引类型,但是会把索引变为可选:

type Partial

= { [P in keyof T]?: T[P]; };1.

测试下:

Extract

Extract 是取两个联合类型都包含的部分,也就是取交集:

type Extract = T extends U ? T : never;1.

测试下:

Exclude

Exclude 是从联合类型 A 中去掉联合类型 B 中的类型,也就是取差集:

type Extract = T extends U ? T : never;1.

测试下:

学会了用 Pick、Partial、Exclude、Extract 这些高级类型,那上面的那段逻辑我们就知道怎么实现了:

只有 A 中有的就保留的逻辑是:Pick>。

A、B 都有的变为可选:Partial>>。

B 中有但 A 中没有的也变为可选:Partial>>。

这样,这个类型的主要逻辑我们就理清了:

把三部分计算结果的索引类型取交叉类型,就会合并到一起。

那前面那两个判断是啥?

P extends any 还有这个 string extends keyof P,这俩都是做啥的?

P extends any 这个是因为联合类型当作为类型参数出现在条件类型左边时,会把每个类型单独传入做计算,最后把计算结果合并成联合类型,这个特性叫做分布式条件类型。

因为 Item 是类型参数,出现在了条件类型的左边,而且传入的是联合类型,那就触发分发特性,会把每个类型单独传入做计算,然后把结果合并成联合类型。

所以这里的 P extends any 的作用就是触发联合类型特性的,从而让这个类型能正确处理联合类型。不然联合类型整个传入的话,后面怎么做计算。

这里的 P extends any 换成 P extends P 也可以,都是一样的作用。

那后面那段代码 string extends keyof P 是啥意思?

这个我确实想了一段时间,如果 { a: 1, b: 2} 这样的索引类型,keyof 的结果是 'a' | 'b',而如果是数组类型,那 keyof 的结果是 0 | 1 | 'length' | 'toString' | ...

什么类型的 keyof 结果是 string 呢?

突然,我想起了前几天学到的一个知识点:用 keyof any 代替 string | number | symbol 更灵活:

而且我试了下 never 的 keyof 结果也是这个:

所以说 string extends keyof P 就可以排除 any 和 never 的情况!

妙呀,还能这么区分 any 和 never。

所以说,这个类型的逻辑我们已经理清了:

这个类型的功能是保留只有 A 有的索引,把 A、B 都有的索引变为可选,把只有 B 有的索引变为可选。

而且处理了联合类型的情况。

如果传入的是 any 或者 never,不做处理,直接返回。

这个类型里我们也学到了不少东西。

总结

我看了下 @types/react 的类型定义,学到了不少东西:

  • 可选索引的值的提取,用 infer 比 Obj[key] 更方便,因为前者只需要 Obj[Key] extends { xxx?: infer Value: undefined},而后者需要先排除值的类型就是 undefined 的情况,然后再用 Exclude 去掉类型中的 undefined。
  • ts 3.0 中取索引类型没有的索引会返回 {} 而不是 never,需要兼容的话可以单独做下判断:'xxx' in keyof Obj。
  • 处理索引类型可以综合用 Pick、Partial、Exclude、Extract 等内置高级类型对每一部分索引做处理,然后取交叉类型来合并到一起。
  • P extends any 和 P extends P 的作用是触发联合类型的分发特性的,加上这段处理才能正确处理联合类型,会把每个类型单独传入做计算,最后把结果合并成联合类型。
  • string extends keyof Obj 可以判断出 any 和 never 类型,只有这两种类型取 keyof 的结果是 string | nubmer | symbole,包含 string。

而且,还讲了一个小技巧:

ts 类型只有计算的时候才会求值,如果是索引类型,可以用映射类型的语法创建个一摸一样的索引类型,因为用到了,就会做计算,从而就可以显示出最终的类型。

不得不说,React 类型定义做的挺完善的,考虑到了各种类型的处理,也考虑到了低版本的兼容,从中还是能学到不少东西的。

来源: 神光的编程秘籍

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
中国,这次是真的拿捏住了美国命脉!

中国,这次是真的拿捏住了美国命脉!

星辰故事屋
2024-04-26 19:32:26
美国警察镇压学运,女教授被暴力摔倒上铐,海外网友:这是法西斯!

美国警察镇压学运,女教授被暴力摔倒上铐,海外网友:这是法西斯!

不掉线电波
2024-04-26 15:27:31
布林肯访华最后时刻,接到中方高层接见通知,并在中国举行记者会

布林肯访华最后时刻,接到中方高层接见通知,并在中国举行记者会

王晋博士
2024-04-26 19:18:42
没想到,曝王楠老公郭斌被限制消费,网友:难怪两天开2000公里

没想到,曝王楠老公郭斌被限制消费,网友:难怪两天开2000公里

尘语者
2024-04-26 15:21:16
疯传!某地8203原配抓渣男开房扇耳光!3段28分钟完整版4K高清流出

疯传!某地8203原配抓渣男开房扇耳光!3段28分钟完整版4K高清流出

魔都囡
2024-04-26 08:00:57
侃爷让她穿啥就穿啥,网友:她也愿意的,痛苦并快乐着

侃爷让她穿啥就穿啥,网友:她也愿意的,痛苦并快乐着

三月柳
2024-04-13 15:27:23
有一种“反噬”叫林生斌,保姆纵火案7年后,善恶终有报被应验了

有一种“反噬”叫林生斌,保姆纵火案7年后,善恶终有报被应验了

影孖看世界
2024-04-26 19:54:38
证监会突发!姚前被查

证监会突发!姚前被查

中国基金报
2024-04-26 16:44:04
辅警杀害新婚妻子被判死缓,死者母亲:他隐瞒精神疾病,检方曾建议最严厉处罚

辅警杀害新婚妻子被判死缓,死者母亲:他隐瞒精神疾病,检方曾建议最严厉处罚

潇湘晨报
2024-04-26 19:15:09
奇瑞背后的大赢家

奇瑞背后的大赢家

蓝鲸财经
2024-04-26 15:30:48
中国女留学生澳大利亚失联,在泰国被找到!家人被骗超百万元

中国女留学生澳大利亚失联,在泰国被找到!家人被骗超百万元

南方都市报
2024-04-26 08:44:35
高岗的地位究竟有多高?看这两张合影的站位,你就明白了

高岗的地位究竟有多高?看这两张合影的站位,你就明白了

文史茶馆2020
2024-04-01 14:44:15
蔓延到法国了?外媒曝光画面:马克龙母校发生亲巴勒斯坦抗议活动

蔓延到法国了?外媒曝光画面:马克龙母校发生亲巴勒斯坦抗议活动

环球网资讯
2024-04-26 21:45:15
北京交管部门发布车展出行攻略:建议观众尽量选择公共交通前往

北京交管部门发布车展出行攻略:建议观众尽量选择公共交通前往

北青网-北京青年报
2024-04-25 13:17:06
主板IPO丨一天两家IPO企业齐撤单!今年沪深主板已有38家企业撤单,长三角三省占比超3成

主板IPO丨一天两家IPO企业齐撤单!今年沪深主板已有38家企业撤单,长三角三省占比超3成

时代商学院
2024-04-26 19:15:16
金靖回应不官宣结婚原因,大赞老公舒奕橙温柔,孩子代号首曝光

金靖回应不官宣结婚原因,大赞老公舒奕橙温柔,孩子代号首曝光

扒虾侃娱
2024-04-25 20:46:34
为什么说回民女人 下边 带盖,关于这几点你知道多少

为什么说回民女人 下边 带盖,关于这几点你知道多少

书中自有颜如玉
2024-04-26 17:25:21
果然没谈拢,布林肯访华,大批外资撤离中国,美国反帮了普京大忙

果然没谈拢,布林肯访华,大批外资撤离中国,美国反帮了普京大忙

朝晖前哨
2024-04-26 09:59:31
高考重大改革!“985”、“211”时代终结,“101计划”时代全面到来!

高考重大改革!“985”、“211”时代终结,“101计划”时代全面到来!

创作者_1494406553502
2024-04-26 15:20:11
探花翻车事故:女子拒绝换姿势态度嚣张被扇脸最后双方互殴

探花翻车事故:女子拒绝换姿势态度嚣张被扇脸最后双方互殴

挪威森林
2024-04-26 20:45:21
2024-04-27 03:14:44
Nodejs开发
Nodejs开发
分享只有程序员懂的干货
648文章数 824关注度
往期回顾 全部

科技要闻

车展观察|德系日系绝不能放弃中国市场

头条要闻

官方回应环卫工用电子秤测灰尘:正常作业达标有奖励

头条要闻

官方回应环卫工用电子秤测灰尘:正常作业达标有奖励

体育要闻

蒙彼利埃vs南特:勒孔特、萨瓦尼耶首发,科科、穆萨-西索科出战

娱乐要闻

金靖回应不官宣恋情结婚的原因

财经要闻

贾跃亭,真他娘是个人才

汽车要闻

2024北京车展 比亚迪的自驱力让对手紧追猛赶

态度原创

房产
时尚
教育
艺术
军事航空

房产要闻

海南最新房价出炉,三亚跌价最猛!

近五年最好笑打脸事件,繁殖狂富豪被捞女骗了?

教育要闻

淄博中考,普通生只会硬算,学霸讲究方法效率

艺术要闻

画廊周北京迎来第八年, “漂留” 主题聚集 30 余家艺术机构与 40 场展览

军事要闻

以军称已完成对拉法地面军事行动准备工作

无障碍浏览 进入关怀版