paint-brush
使用解构和内联类型可能会损害您的 TypeScript 代码库经过@baransu
1,271 讀數
1,271 讀數

使用解构和内联类型可能会损害您的 TypeScript 代码库

经过 Tomasz Cichociński4m2022/10/10
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

使用解构和内联类型会降低 TypeScript 的可读性。我想向您展示如何使用解构使其在 TypeScript 中的可读性降低。它不鼓励创建较小的辅助函数并依赖组合来构建您的主函数逻辑。当所有类型都被函数定义中的解构所束缚时,没有自然的地方可以编写文档注释。它只是大量的代码空间,并且占用了大量的代码行空间。此外,除了实现细节之外,它还关注实现细节。

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - 使用解构和内联类型可能会损害您的 TypeScript 代码库
Tomasz Cichociński HackerNoon profile picture
0-item


最近我看到 Jamie Kyle 关于使用解构、默认参数和内联类型的推文:


我最近在日常工作中看到的那条推文和一些 React 组件启发了我写这篇博文。我想向你展示使用解构和内联类型如何降低 TypeScript 的可读性!


TypeScript 函数定义是什么样的?

在 JavaScript 和 TypeScript 中,您可以使用function关键字或 lambda/arrow 函数来定义函数。两种方式都有效,但也有区别。让我们看一下简单的sendMessage函数。实现逻辑与我们无关。


 // sendMessage function written using `function` keyword function sendMessage(message: string) { // function logic } // same sendMessage written as arrow function const sendMessage = (message: string) => { // function logic };


当函数定义非常简单时,函数接受一些不同类型的参数。如果它们是字符串或数字之类的原语,那么一切都是可读的。


假设您想将一些附加信息与您的消息内容一起传递给sendMessage函数。


 function sendMessage(message: { content: string; senderId: string; replyTo?: string; }) { // you can assess content using `message.content` here }


如您所见,TypeScript 允许您为要传递的message对象编写内联类型定义,而无需使用typeinterface关键字指定类型。


让我们添加解构。当您将大型message对象传递给您的函数时,TypeScript 允许拆分传递的参数以减少多次重复message变量的代码样板。


 function sendMessage({ content, senderId, replyTo, }: { content: string; senderId: string; replyTo?: string; }) { // you have access to `content` directly }


为什么我认为这是一个坏主意以及如何使它变得更好?

这可能看起来是个好主意,毕竟你不需要写那么多次message ,对吧?事实证明这并不是那么好。让我们谈谈我认为它是反模式的 5 个原因。


1. 你不确定你的数据来自哪里

当您阅读函数体时,您会看到senderId您必须仔细检查以确保该函数来自何处。它是作为参数传递还是在函数的某处计算?


2. 很难写文档

当所有类型都被函数定义中的解构所束缚时,没有自然的地方可以编写文档注释。您可以在每个类型字段之间写注释,但这会使整个函数定义更长。它积极地阻止您编写您传递的数据的快速摘要。


3. 很难将数据向前传递

当您的数据被解构时,如果您想将其向前传递,则需要再次将其结构化为一个新对象。这不鼓励创建较小的辅助函数并依赖组合来构建您的主函数逻辑。


4. 你不能在这个函数之外重用参数类型

如果在编写主函数逻辑时需要在辅助函数中重用函数参数,则必须重复键入同一组类型。这使得根本不编写类型变得更容易。


5.它只需要很多空间

面对现实吧。这只是占用大量屏幕空间的大量代码行。此外,它侧重于实现细节——您传递给函数的参数的内部类型,这在您查看该函数时大部分时间并不相关。


只需为它创建一个类型

提取类型并将其放在函数的正上方使其更具可读性。有一个文档注释的地方,您可以在其他一些辅助函数中重用该类型,并在需要时在一个地方更改类型定义。


 /** * Message to send using XYZ API */ export type MessageToSend = { /** * Markdown string of the user's message */ content: string; /** * Id of the sender user */ senderId: string; /** * Other message ID if this is a reply */ replyTo?: string; }; function sendMessage(message: MessageToSend) { // function logic } function getUserIdsToNotify(message: MessaageToSend) { // function logic }


资源

查找我在研究此博客文章时使用的资源列表: