前端开发者应该知道的TypeScript可区分联合

图片

作为一个前端开发者,你的工作不仅仅是移动像素,前端的大部分复杂性来自于处理你的应用程序可能处于的所有不同状态。

它可能是加载数据,等待表单被填写,或者发送一个遥测事件 - 或者同时进行这三项。

如果不能正确处理状态,就可能陷入困境,而处理状态要从它们在类型中如何表示开始。

“可选包”

假设你正在构建一个简单的数据加载器,你可以选择使用如下类型来表示其状态:

 
interface State {  status: "loading" | "error" | "success";  error?: Error;  data?: { id: string };}// Some examples:const example: State = {    status: "loading"};const example2: State = {    status: "error",    error: new Error("Oh no!")};

这看起来很不错 - 我们可以检查  status  来理解我们应该在屏幕上显示哪种 UI。

除了 - 这种类型让我们声明所有应该不可能的形状:

 
const example3: State = {  status: "success",  // Where's the data?!};

这里,我们处于成功状态 - 这应该让我们访问数据。但它不存在!

 
const example4: State = {  status: "loading",  // We're loading, but we still have an error?!  error: new Error("Eek!"),};

在这里,我们处于加载状态 - 但我们的数据对象仍然有一个错误!

这是因为我们选择使用我称之为“可选包”的状态来表示我们的状态——一个充满可选属性的对象。

可选属性最好用于值可能存在或可能不存在的情况,在本例中,这是不正确的。

  • 当 status 是 loading 时, data 或 error 永远不存在。

  • 当 status 是 success 时, data 总是存在。

  • 当 status 是 error 时, error 总是存在。


可区分联合
 

更准确地表示这种情况的方法是使用 discriminated union,即可区分联合。

让我们从将状态更改为对象的联合开始,每个对象都包含一个状态。

 
type State =  | {      status: "loading";    }  | {      status: "success";    }  | {      status: "error";    };

现在我们已经有了基本框架,可以开始向联合的每个分支添加元素了。让我们重新添加错误和数据类型。

 
type State =  | {      status: "loading";    }  | {      status: "success";      data: {        id: string;      };    }  | {      status: "error";      error: Error;    };

现在,上面的例子将开始出错。

 
// Error: Property 'data' is missingconst example3: State = {  status: "success",};const example4: State = {  status: "loading",  // Error: Object literal may only specify known  // properties, and 'error' does not exist  error: new Error("Eek!"),};

我们的  State  类型现在正确地表示了特性的所有可能状态,这是向前迈出的一大步,但我们还没有完成。


解构可区分联合
 

让我们假设我们位于代码库中的组件内部,我们已经接收到状态片段,并希望使用它来渲染一些 JSX。

我在这里使用 React,但这可以是任何前端框架。

许多开发人员的第一反应是解构  State  的元素,但您会立即遇到错误:

 
const Component = () => {  const [state, setState] = useState<State>({    status: "loading",  });  const {    status,    // Error: Property 'data' does not exist on type 'State'.    data,    // Error: Property 'error' does not exist on type 'State'.    error,  } = state;};

对于许多开发者来说,这将是棘手的问题,因为  data  和  error  都可以存在于  State  上,所以为什么我得到错误?

原因是我们还没有试图区分这个 union,我们不知道自己在哪个状态,所以唯一可用的属性是 union 中所有成员共享的属性,即  status 。

一旦我们检查了我们所在的联合分支,我们就可以安全地解构  state !

 
if (state.status === "success") {  const { data } = state;}

这种严格性是一个特性,而不是一个 bug,通过确保你只能在状态等于  success  时访问数据,鼓励你从状态的角度来考虑应用,并且只在可用的状态下访问数据。


总结
 

当你开始从区分状态的角度考虑你的应用时,很多事情就变得容易了。

你将开始理解数据和 UI 之间的联系,而不是一个可选的大数据包。

不仅如此,你还能以一种全新的方式思考属性。

如果你需要以两种略有不同的方式显示组件,可以使用 discriminated union:

 
type ModalProps =  | {      variant: "with-description-and-button";      buttonText: string;      description: string;      title: string;    }  | {      variant: "base";      title: string;    };

这里,只有当传入的变量是  with-description-and-button  时,才需要  buttonText  和  description 。

 

欢迎关注公众号:文本魔术,了解更多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/448887.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#,哥伦布数(Golomb Number)的算法与源代码

1 哥伦布数&#xff08;Golomb Number&#xff09; 哥伦布数&#xff08;Golomb Number&#xff09;是一个自然数的非减量序列&#xff0c;使得n在序列中正好出现G&#xff08;n&#xff09;次。前几个15的G&#xff08;n&#xff09;值为&#xff1a;1 2 2 3 3 4 4 4 5 5 5 6…

Leetcode2855. 使数组成为递增数组的最少右移次数

Every day a Leetcode 题目来源&#xff1a;2855. 使数组成为递增数组的最少右移次数 解法1&#xff1a;暴力 由于右移 n 次就变回原数组了&#xff0c;所以答案至多为 n−1。 枚举右移次数&#xff08;1~n-1&#xff09;&#xff0c;每次右移一个元素后判断数组是否有序&…

MATLAB实现随机森林(RF)回归与自变量影响程度分析

本文分为两部分&#xff0c;首先是对代码进行分段、详细讲解&#xff0c;方便大家理解&#xff1b;随后是完整代码&#xff0c;方便大家自行尝试。另外&#xff0c;关于基于MATLAB的神经网络&#xff08;ANN&#xff09;代码与详细解释&#xff0c;我们将在后期博客中介绍。 1…

算法练习-二叉树的节点个数【完全/普通二叉树】(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;二叉树 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0c;旨…

2024年美赛B题潜水器定位和搜救建模代码和完整论文文档

目前已完成2024年美赛B题潜水器定位和搜救的建模代码和论文编写&#xff0c;部分文章内容和代码如下&#xff1a; 摘要 在海洋探险和搜救领域&#xff0c;潜水器的定位和搜救任务具有重要意义。本文旨在开发一系列模型来预测潜水器位置、分析不确定性、确定信息传递策略、建议…

[UI5 常用控件] 05.FlexBox, VBox,HBox,HorizontalLayout,VerticalLayout

文章目录 前言1. FlexBox布局控件1.1 alignItems 对齐模式1.2 justifyContent 对齐模式1.3 Direction1.4 Sort1.5 Render Type1.6 嵌套使用1.7 组件等高显示 2. HBox,VBox3. HorizontalLayout&#xff0c;VerticalLayout 前言 本章节记录常用控件FlexBox,VBox,HBox,Horizontal…

说说RDB和AOF

简介&#xff1a; 众所周知&#xff0c;redis是一个内存数据库&#xff0c;当机器重启后&#xff0c;内存中数据都会丢失。所以redis提供了两种持久化方式&#xff0c;即&#xff1a;RDB(保存一个时间点前的数据)和AOF(保存redis服务器端执行的每一条命令)。 RDB: RDB有两种…

Web实战丨基于django+hitcount的网页计数器

文章目录 写在前面Django简介主要程序运行结果系列文章写在后面 写在前面 本期内容 基于djangohitcount的网页计数器 所需环境 pythonpycharm或vscodedjango 下载地址 https://download.csdn.net/download/m0_68111267/88795611 Django简介 Django 是一个开源的、基于 …

DES加密原理

DES加密算法综合运用了置换、代替、代数等多种密码技术&#xff0c;具有设计精 巧、实现容易、使用方便等特点。DES加密算法的明文、密文和密钥的分组长度 都是64位&#xff0c;详细的DES加密算法结构如图6-10所示。 图6-10 DES加密算法结构图 DES加密过程如下所示&#xff…

Linux系统漏洞一键检测与修复工具

支持检测及修复漏洞的列表 OpenSSL CVE-2021-3712 OpenSSH CVE-2021-41617 sudo CVE-2021-3156 glibc CVE-2018-11236 polkit CVE-2021-4034 wget CVE-2017-13090 kernel CVE-2016-5195 bash CVE-2016-7543 samba CVE-2021-…

代码随想录第二十四天| 回溯算法● 理论基础 ● 77. 组合

文章目录 理论基础![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/09da30301c104f02baf792ccbf39da15.png)效率回溯法解决的问题如何理解回溯法回溯法模板 77.组合思路&#xff1a;回溯法三部曲 代码&#xff1a;思路-剪枝代码&#xff1a; 理论基础 效率 虽然回…

后端——go系统学习笔记(不断更新中......)

数组 固定大小 初始化 arr1 : [3]int{1, 2, 3} arr2 : [...]int{1, 2, 3} var arr3 []int var arr4 [4]int切片 长度是动态的 初始化 arr[0:3] slice : []int{1,2,3} slice : make([]int, 10)len和cap len是获取切片、数组、字符串的长度——元素的个数cap是获取切片的容量—…