精进TypeScript--【类型设计】倾向选择总是代表有效状态的类型

本文主要是介绍精进TypeScript--【类型设计】倾向选择总是代表有效状态的类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如果你看不到代码所操作的数据或数据类型,代码就很难理解。这就是类型系统的一大优势:通过写出类型,让你的代码的读者可以看到它们,而且这也将使得你的代码变得易懂。

要记住的事情:

  • 既代表有效状态又代表无效状态的类型,很可能使得代码混乱,容易出错
  • 优先选择只代表有效状态的类型。即使它们较长或较难表达,但最终会为你节省时间和较少痛苦

假设你正在构建一个Web应用程序,允许你选择一个页面,加载该页面的内容,然后显示它:

interface State {pageText: string;isLoading: boolean;error?: string;
}

当你编写代码来渲染页面时,你需要考虑所有这些领域:

function renderPage(state: State) {if (state.error) {return `Error! Unable to load ${currentPage}: ${state.error}`;} else if (state.isLoading) {return `Loading ${currentPage}...`;}return `<h1>${currentPage}</h1>\n${state.pageText}`;
}

上面的做法对吗?如果 isLoading 和 error 都设置了呢?是显示加载信息好还是错误信息好?这个很难说,目前信息量不够。

或者,如果你要写一个changePage函数呢?比如:

async function changePage(state: State, newPage: string) {state.isLoading = true;try {const response = await fetch(getUrlForPage(newPage));if (!response.ok) {throw new Error(`Error! Unable to load ${newPage}: ${response.statusText}`);}const text = await response.text();state.isLoading = false;state.pageText = text;} catch(e) {state.error = '' + e;}
}

这里有很多问题:

  • 在错误的情况下,我们忘记将 state.isLoading 设置为 false
  • 我们没有清除 state.error,所以如果之前的请求失败,那么你会一直看到这个错误信息,而不是加载信息
  • 如果用户在页面加载过程中再次刷新页面,谁也不知道会发生什么。他们可能会看到一个新的页面,然后出现一个错误:或者看到第一个页面,而不是第二个页面,这取决于响应回来的顺序

问题在于状态包括的信息太少:哪个请求失败了?哪个正在加载?或者包括的信息太多:State 类型允许设置 isLoading 和 error,即使这代表一个无效的状态。这使得 render() 和 changePage() 都无法很好地实现。

这里有一种更好的方式来表示应用状态:

interface RequestPending {state: 'pending';
}
interface RequestError {state: 'error';error: string;
}
interface RequestSuccess {state: 'ok';error: string;
}
type RequestState = RequestPending | RequestError | RequestSuccess;interface State {currentPage: string;requests: {[page: string]: RequestState};
}

这里使用一个标签联合类型来明确地模拟网络请求可能处于的不同状态。尽管这个版本的状态要更长,但它有一个巨大的优势,就是不接受无效 状态。当前页面是基于显式建模的,你发出的每个请求的状态也是基于显式建模的。因此,renderPage 和 changePage 函数很容易实现:

function renderPage(state: State) {const {currentPage} = state;const requestState = state.requests[currentPage];switch (requestState.state) {case 'pending':return `Loading ${currentPage}...`;case 'error':return `Error! Unable to load ${currentPage}: ${requestState.error}`;case 'ok':return `<h1>${currentPage}</h1>\n${requestState.pageText}`;case default:return '';}
}async function changePage(state: State, newPage: string) {state.requests[newPage] = {state: 'pending'};state.currentPage = newPage;try {const response = await fetch(getUrlForPage(newPage));if (!response.ok) {throw new Error(`Error! Unable to load ${newPage}: ${response.statusText}`);}const pageText = await response.text();state.requests[newPage] = {state: 'ok', pageText};} catch(e) {state.requests[newPage] = {state: 'error', error: '' + e};}
}

和第一次实现相比,歧义完全消失了。当前页面是什么很清楚,每一个请求正好对应一个状态。如果用户在请求发出后改变了页面,那也没有问题。旧的请求仍然会完成,但不会影响 UI。

这篇关于精进TypeScript--【类型设计】倾向选择总是代表有效状态的类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/883811

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

hdu1565(状态压缩)

本人第一道ac的状态压缩dp,这题的数据非常水,很容易过 题意:在n*n的矩阵中选数字使得不存在任意两个数字相邻,求最大值 解题思路: 一、因为在1<<20中有很多状态是无效的,所以第一步是选择有效状态,存到cnt[]数组中 二、dp[i][j]表示到第i行的状态cnt[j]所能得到的最大值,状态转移方程dp[i][j] = max(dp[i][j],dp[i-1][k]) ,其中k满足c

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte