精进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

相关文章

Pydantic中Optional 和Union类型的使用

《Pydantic中Optional和Union类型的使用》本文主要介绍了Pydantic中Optional和Union类型的使用,这两者在处理可选字段和多类型字段时尤为重要,文中通过示例代码介绍的... 目录简介Optional 类型Union 类型Optional 和 Union 的组合总结简介Pyd

关于WebSocket协议状态码解析

《关于WebSocket协议状态码解析》:本文主要介绍关于WebSocket协议状态码的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录WebSocket协议状态码解析1. 引言2. WebSocket协议状态码概述3. WebSocket协议状态码详解3

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

一文教你PyCharm如何有效地添加源与库

《一文教你PyCharm如何有效地添加源与库》在使用PyCharm进行Python开发的时候,很多时候我们需要添加库或者设置源,下面我们就来和大家详细介绍一下如何在PyCharm中添加源和库吧... 在使用PyCharm进行python开发的时候,很多时候我们需要添加库或者设置源。这些操作可以帮助我们更方便

Python如何查看数据的类型

《Python如何查看数据的类型》:本文主要介绍Python如何查看数据的类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录python查看数据的类型1. 使用 type()2. 使用 isinstance()3. 检查对象的 __class__ 属性4.

Python容器类型之列表/字典/元组/集合方式

《Python容器类型之列表/字典/元组/集合方式》:本文主要介绍Python容器类型之列表/字典/元组/集合方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 列表(List) - 有序可变序列1.1 基本特性1.2 核心操作1.3 应用场景2. 字典(D

OpenManus本地部署实战亲测有效完全免费(最新推荐)

《OpenManus本地部署实战亲测有效完全免费(最新推荐)》文章介绍了如何在本地部署OpenManus大语言模型,包括环境搭建、LLM编程接口配置和测试步骤,本文给大家讲解的非常详细,感兴趣的朋友一... 目录1.概况2.环境搭建2.1安装miniconda或者anaconda2.2 LLM编程接口配置2

Linux虚拟机不显示IP地址的解决方法(亲测有效)

《Linux虚拟机不显示IP地址的解决方法(亲测有效)》本文主要介绍了通过VMware新装的Linux系统没有IP地址的解决方法,主要步骤包括:关闭虚拟机、打开VM虚拟网络编辑器、还原VMnet8或修... 目录前言步骤0.问题情况1.关闭虚拟机2.China编程打开VM虚拟网络编辑器3.1 方法一:点击还原VM

Python如何在Word中生成多种不同类型的图表

《Python如何在Word中生成多种不同类型的图表》Word文档中插入图表不仅能直观呈现数据,还能提升文档的可读性和专业性,本文将介绍如何使用Python在Word文档中创建和自定义各种图表,需要的... 目录在Word中创建柱形图在Word中创建条形图在Word中创建折线图在Word中创建饼图在Word