147. 精读《@types react 值得注意的 TS 技巧》

2023-11-10

1 引言

从 @types/react 源码中挖掘一些 Typescript 使用技巧吧。

2 精读

泛型 extends

泛型可以指代可能的参数类型,但指代任意类型范围太模糊,当我们需要对参数类型加以限制,或者确定只处理某种类型参数时,就可以对泛型进行 extends 修饰。

问题:React.lazy 需要限制返回值是一个 Promise<T> 类型,且 T 必须是 React 组件类型。

方案:

function lazy<T extends ComponentType<any>>(
  factory: () => Promise<{ default: T }>
): LazyExoticComponent<T>;

T extends ComponentType 确保了 T 这个类型一定符合 ComponentType 这个 React 组件类型定义,我们再将 T 用到 Promise<{ default: T }> 位置即可。

泛型 extends + infer

如果有一种场景,需要拿到一个类型,这个类型是当某个参数符合某种结构时,这个结构内的一种子类型,就需要结合 泛型 extends + infer 了。

问题:React.useReducer 第一个参数是 Reducer,第二个参数是初始化参数,其实第二个参数的类型是第一个参数中回调函数第一个参数的类型,那我们怎么将这两个参数的关系联系到一起呢?

方案:

function useReducer<R extends Reducer<any, any>, I>(
  reducer: R,
  initializerArg: I & ReducerState<R>,
  initializer: (arg: I & ReducerState<R>) => ReducerState<R>
): [ReducerState<R>, Dispatch<ReducerAction<R>>];

type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any>
  ? S
  : never;

R extends Reducer<any, any> 的意思在上面已经提过了,也就是 R 必须符合 Reducer 结构,也就是 reducer 必须符合这个结构,之后重点来了:initializerArg 利用 ReducerState 这个类型直接从 reducer 的类型 R 中将第一个回调参数挖了出来并返回。

ReducerState 定义中 R extends Reducer<infer S, any> ? S : never 的含义是:如果 R 符合 Reducer<infer S, any> 类型,则返回类型 S,这个 S 是 Reducer<infer S> 也就是 State 位置的类型,否则返回 never 类型。

所以 infer 表示待推断类型,是非常强大的功能,可以指定在任意位置代指其类型,并配合 extends 判断是否符合结构,可以使类型推断具备一定编程能力。

要用 extends 的另一个原因是,只有 extends 才能将结构描述出来,我们才能精确定义 infer 指代类型的位置。

类型重载

当一个类型拥有多种使用可能性时,可以采用类型重载定义复数类型,Typescript 作用时会逐个匹配并找到第一个满足条件的。

问题:createElement 第一个参数支持 FunctionComponent 与 ClassComponent,而且传入参数不同,返回值的类型也不同。

方案:

function createElement<P extends {}>(
  type: FunctionComponent<P>,
  props?: (Attributes & P) | null,
  ...children: ReactNode[]
): FunctionComponentElement<P>;
function createElement<P extends {}>(
  type: ClassType<
    P,
    ClassicComponent<P, ComponentState>,
    ClassicComponentClass<P>
  >,
  props?: (ClassAttributes<ClassicComponent<P, ComponentState>> & P) | null,
  ...children: ReactNode[]
): CElement<P, ClassicComponent<P, ComponentState>>;

将 createElement 写两遍及以上,并配合不同的参数类型与返回值类型即可。

自定义类型收窄

我们可以通过 typeof 或 instanceof 做一些类型收窄工作,但有些类型甚至自定义类型的收窄判断函数需要自定义,我们可以通过 is 关键字定义自定义类型收窄判断函数。

问题:isValidElement 判断对象是否是合法的 React 元素,我们希望这个函数具备类型收窄的功能。

方案:

function isValidElement<P>(
  object: {} | null | undefined
): object is ReactElement<P>;

const element: string | ReactElement = "";

if (isValidElement(element)) {
  element; // 自动推导类型为 ReactElement
} else {
  element; // 自动推导类型为 string
}

基于这个方案,我们可以创建一些很有用的函数,比如 isArrayisMapisSet 等等,通过 is 关键字时其被调用时具备类型收窄的功能。

用 Interface 定义函数

一般定义函数类型我们用 type,但有些情况下定义的函数既可被调用,也有一些默认属性值需要定义,我们可以继续用 Interface 定义。

问题:FunctionComponent 既可以当作函数调用,同时又能定义 defaultProps displayName 等固定属性。

方案:

interface FunctionComponent<P = {}> {
  (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
  propTypes?: WeakValidationMap<P>;
  contextTypes?: ValidationMap<any>;
  defaultProps?: Partial<P>;
  displayName?: string;
}

(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null 表示这种类型的变量可以作为函数执行:

const App: FunctionComponent = () => <div />;
App.displayName = "App";

3 总结

看完文章内容,相信你已经可以独立读懂 @types/react 这个包的所有类型定义!

更多基础内容可以阅读 精读《Typescript2.0 - 2.9》 与 精读《Typescript 3.2 新特性》,由于 TS 更新频繁,后续 TS 技巧可能继续以阅读源码方式进行,希望这次选用的 React 类型源码可以让你印象深刻。

更多讨论

如果你想参与讨论,请关注前端精读 周刊- 每周一帮你筛选靠谱的内容。

以下是我个人微信,欢迎交流(加好友注明来自前端精读)!

(如想获得阿里内推机会,发简历给我,邮箱地址:

ziyi.hzy@alibaba-inc.com

PS:招人阶段,欢迎大家砸简历~)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

147. 精读《@types react 值得注意的 TS 技巧》 的相关文章

  • Python 100 天从新手到大师

    早上好 骚年 我是小菜 我的公众号 菜鸟翻身 会推荐 GitHub 上有用的项目 一分钟 get 一个优秀的开源项目 挖掘开源的价值 我的引语 今天推荐是一个 Python 基础教程 按照教程学习 不出意外 100 天从新手到大师 当下 P
  • disable path和false path的作用与区别

    disable path和false path的作用与区别C 欢迎使用Markdown编辑器 链接 disable与false的相同与不同 false path 指定某一条path 工具计算delay 但不报时序 disable path
  • Java环境变量的配置

    最近有朋友问到环境变量的配置 下面以Windows10系统为例进行Java环境变量配置说明 1 右键点击 此电脑 选择 属性 项 2 点击 高级系统设置 在弹出的系统属性框中 选择 高级 选项卡 默认即显示该选项卡 点击 环境变量 3 在弹
  • 回答问题:你认为AGI应该采用什么思路?

    我是研究AGI基础理论的 我认为AGI要突破首先要对智能的原理有突破 需要建立一套体系描述和解释智能 我认为目前的数学体系有很大的不足 限制了人类对智能的理解 所以需要改革 重新理解一些基础的东西 例如 空间的本质 计算的本质 我认为AGI
  • C++Opencv图像对象Mat的创建和赋值

    Mat中元素的类型以及矩阵的通道个数 它是一系列的预定义的常量 其命名规则为CV 位数 数据类型 通道数 因此在学习图像创建之前先了解一下基本的数据类型 S 有符号整型 U 无符号整型 F 浮点型 CV 8U 8位无符号整数 CV 8S 8
  • Windows CE嵌入式导航系统研究(内核相关)

    1 1 嵌入式车载导航系统的软件设计流程 嵌入式车载系统软件主要包括系统内核 驱动程序 应用程序三部分 设计的过程当中 我们采用瀑布模型进行设计 首先制定Windows CE5 0系统内核 再次编写相关设备驱动 最后编写或移植应用程序 制定
  • 软件测试实验二 白盒测试

    一 实验目的 1 掌握等逻辑覆盖测试法 2 掌握基本路径测试法 3 掌握基于Junit的单元测试 二 实验内容 1 为以下判断等级的程序段设计一组测试用例 要求分别满足语句覆盖 判定覆盖 条件覆盖 判断 条件覆盖 条件组合覆盖 public
  • 809协议nodejs编写笔记

    一 总体流程 数据首先通过receiver接受层接收 去掉标识头和标识尾 再进入depacker解包层进行解包 把标识头分解出来并解析 之后发给handler处理层根据不同的消息id选择使用不同的业务逻辑 如果有应答 则通过sender发送
  • 7.12 redis未授权访问漏洞

    在1 txt添加存在redis未授权访问漏洞的IP redis py输入脚本 redis cli exe h IP p 端口号
  • async/await 异步函数

    1 async异步函数的使用 await async写法 async function foo1 const foo2 async gt 2 async异步函数的执行流程 都是同步代码 跟普通函数代码没区别 async function f
  • RTP - 视频流广播

    这是用RTP RFC3350 按RFC2550封装MPEG ES流数据的发送程序 学习RTP的路真的辛苦 在网上收集的有关RTP的程序都是那种只负责RTP数据包发送的库 如jrtplib等 他们的DEMO 程序都只是用来发发字符串 编编聊天
  • mac mongodb Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols

    mac 下 mongodb 执行命令 mongod 报错 标题为报错的第一句 因为一般人百度的时候都是根据第一句百度 所以起的这个标题 具体报错如下图 我的具体信息如上 可以发现 报错的主要信息在于 没有找到 data 数据的存放路径导致的
  • 【华为OD统一考试A卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • 【数据结构前置知识】初识集合框架和时间,空间复杂度

    文章目录 1 什么是集合框架 2 集合框架的重要性 3 背后所涉及的数据结构以及算法 3 1 什么是数据结构 3 2 容器背后对应的数据结构 3 3 相关java知识 3 4 什么是算法 4 时间复杂度 1 如何衡量一个算法的好坏 2 算法
  • js高级 6.闭包

    闭包的理解 如何产生闭包 当一个嵌套的内部 子 函数引用了嵌套的外部 父 函数的变量 或函数 时 就产生了闭包 闭包到底是什么 使用chrome浏览器查看 理解一 闭包是嵌套的内部函数 大多数人 理解二 包含被引用变量 或函数 的对象 极少
  • 进程与线程408

    文章目录 1 进程与线程 1 1 进程的概念与特征 1 2 进程的状态与转换 1 3 进程的组成 1 4进程控制 1 5 进程的通信 2 处理机调度 2 1 调度的基本概念 2 2 调度算法的评价指标 2 3 调度的实现 2 4 经典的调度
  • 单相电流型逆变电路

    电流型逆变电路 引言 电流型三相桥式逆变电路 直流电源为电流源的逆变电路称为电流型逆变电路 电流型逆变电路主要特点 直流侧串大电感 电流基本无脉动 相当于电流源 交流输出电流为矩形波 与负载阻抗角无关 输出电压波形和相位因负载不同而不同 直
  • C# DropDownList绑定添加新数据的几种方法

    第一种 在前台手动绑定 适用于固定不变的数据项
  • 第2课 微信开发者工具使用slider进度条标签编写rgb颜色选择功能:

    微信小程序编写rgb颜色选择功能 效果图如下 以下是wxml文件代码
  • 银行应用软件:零售银行业务中谁才是赢家

    资本界的谷歌 这就是杰里米 阿莱尔现在正在创建的 也就是 一家消费者金融公司 为消费者提供存款 寄款和收款产品 这些也是零售银行的基础公共设施 42 他 认为对任何有上网设备的人来说 这都是一个强大 实时及免费的服务 而他的区块链公司世可国

随机推荐

  • PHP微信公众开发笔记(一)

    笔记是先写在印象笔记上的 晚上没事的时候整理整理 PHP微信公众开发笔记系列 日期 2014 9 1 今天开始正式开始做班上的微信公众平台的开发者服务了 因为是第一次做这个 对PHP也不了解 所以一边学PHP 一边整理微信的公众平台 当做是
  • Qt中的JSON操作_3: JSON在Qt中的应用举例(写入和读出的关键是利用QJsonDocument实现Json格式的文件转换为字符串)

    接上篇 Qt中的JSON操作 2 JSON在Qt中的使用 本篇主要讲利用Json在Qt中封装的类实现读写文件的举例 我们在Qt中的JSON操作 1 JSON的基本知识介绍中举了一个Json对象的例子 对象1中嵌入对象2 对象2中嵌入数组 对
  • error ‘defineProps‘ is not defined no-undef

    error defineProps is not defined no undef 例如defineProps和defineEmits生成no undef警告 示例 eslintrc js module exports env vue se
  • SpringBoot获取项目日志

    目的 对于布署在远端的服务 我们想快速的获取到日志 对于使用了日志服务 也可能因为上报间隔太长 日志不够实时 所以想通过一些方式 可以不用进入到容器内也可以简单快速获取到日志 而且是实时的日志 目标就是获取最新的n条日志 搜索啥的功能也不需
  • Python(1)--Python安装

    本篇作为学习Python笔记 来记录学习过程 安装环境 windows10 官方下载地址 https www python org 有很多的版本 我这里选择了3 7 2 executable表示可执行版 需要安装后使用 embeddable
  • Python基础 NumPy数组相关概念及操作

    NumPy是Python的一种开源的数值计算扩展库 提供 数组支持以及相应的高效处理函数 它包含很多功能 如创建n维数组 矩阵 对数组进行函数运算 数值积分 线性代数计算 傅里叶变换和随机数产生等 Why NumPy 标准的Python用L
  • CentOS8基础篇2:文件系统

    一 文件系统概述 1 文件系统的基本概念 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统 简称文件系统 它规定了文件的存储方式及文件索引方式等信息 文件系统主要由三部分组成 分别是与文件管理相关的软件 被管理的文件和实施文件管理
  • 神经网络中的神经元和激活函数详解

    在上一节 我们通过两个浅显易懂的例子表明 人工智能的根本目标就是在不同的数据集中找到他们的边界 依靠这条边界线 当有新的数据点到来时 只要判断这个点与边界线的相互位置就可以判断新数据点的归属 上一节我们举得例子中 数据集可以使用一条直线区分
  • jdk13快来了,jdk8的这几点应该看看!

    说明 jdk8虽然出现很久了 但是可能我们还是有很多人并不太熟悉 本文主要就是介绍说明一些jdk8相关的内容 主要会讲解 lambda表达式 方法引用 默认方法 Stream 用Optional取代null 新的日志和时间 Completa
  • 自定义view

    自定义View 有这一篇就够了 简书 jianshu com
  • STM32cubeProgrammer连接设置说明

    芯片型号 STM32F427 连接 connect Frequency设置为200 点击connection REG模块 随后device选STM32F427 peripheral选择GPIOD
  • android应用安装成功之后删除apk文件

    摘要 题目 正在运用开辟中碰到须要如许的需供 正在用户下载我们的运用装置以后删除装置包 办理 android会正在每一个中界操纵APK的举措以后收回体系级其余播送 过滤器称号 问题 在应用开发中遇到需要这样的需求 在用户下载我们的应用安装之
  • C语言学前班

    C 语言学前班 10分钟入门 10天练习 哪有那么难 根本用不着科班通过上课学几个月 程序 数据结构 算法 数据结构 容器来存储要进行各种操作的数据 算法 对各种数据进行各种操作 加减乘除 增删改查 判 判断 排 排序 复 复位 输出结果来
  • Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses 解决方法

    mopondys iMac zyc flutter doctor Doctor summary to see all details run flutter doctor v Flutter Channel dev v1 16 2 on M
  • NVisionXR for ARCore内测版开放申请

    NVisionXR for ARCore引擎能够帮助开发者快速开发原生ARCore应用 只要你懂基本的Android开发 直接使用Android Studio 即可实现动画模型渲染 粒子特效 音视频播放 灯光渲染等功能 NVisionXR引
  • java线程池的使用

    线程池概述 线程池 Thread Pool 是一种基于池化思想管理线程的工具 使用线程池可以带来诸多好处 降低资源消耗 通过池化技术复用已创建的线程 减少线程创建和销毁的损耗 提高响应速度 任务到达时 特定情况下无需再创建线程 便于管理 j
  • hangfire+bootstrap ace 模板实现后台任务管理平台

    前言 前端时间刚开始接触Hangfire就翻译了一篇官方的教程 翻译 山寨 Hangfire Highlighter Tutorial 后来在工作中需要实现一个异步和定时执行的任务管理平台 就结合bootstrap ace模板和hangfi
  • echarts中多y轴图像(柱,折)

    先看看效果吧 var myChart echarts init document getElementById demo echarts zyyh 放入的id var colors e6bcff a3ffcd fefefe option c
  • C++之explicit的作用介绍

    1 C 中的关键字explicit主要是用来修饰类的构造函数 被修饰的构造函数的类 不能发生相应的隐式类型转换 只能以显示的方式进行类型转换 类构造函数默认情况下声明为隐式的即implicit 隐式转换即是可以由单个实参来调用的构造函数定义
  • 147. 精读《@types react 值得注意的 TS 技巧》

    1 引言 从 types react 源码中挖掘一些 Typescript 使用技巧吧 2 精读 泛型 extends 泛型可以指代可能的参数类型 但指代任意类型范围太模糊 当我们需要对参数类型加以限制 或者确定只处理某种类型参数时 就可以