paint-brush
Usar tipos de desestruturação e embutidos pode prejudicar sua base de código TypeScriptpor@baransu
1,271 leituras
1,271 leituras

Usar tipos de desestruturação e embutidos pode prejudicar sua base de código TypeScript

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

Muito longo; Para ler

Usar tipos de desestruturação e embutidos torna seu TypeScript menos legível. Quero mostrar a você como o uso da desestruturação o torna menos legível no TypeScript. Isso desencoraja a criação de funções auxiliares menores e a dependência da composição para construir a lógica da função principal. Não há lugar natural para escrever comentários de documentação quando todos os tipos são limitados pela desestruturação na definição da função. É apenas muito espaço de código e ocupa muito espaço de linhas de código. Além disso, ele se concentra nos detalhes da implementação, além dos detalhes da implementação.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Usar tipos de desestruturação e embutidos pode prejudicar sua base de código TypeScript
Tomasz Cichociński HackerNoon profile picture
0-item


Recentemente, vi um tweet de Jamie Kyle sobre o uso de desestruturação, parâmetros padrão e tipos embutidos:


Esse tweet e alguns componentes do React que vi recentemente em meu trabalho diário me inspiraram a escrever esta postagem no blog. Quero mostrar a você como usar tipos de desestruturação e embutidos pode tornar seu TypeScript menos legível!


Como é a definição da função TypeScript?

Em JavaScript e TypeScript, você pode definir uma função usando a palavra-chave function ou a função lambda/seta. Ambas as formas são válidas, mas têm suas diferenças. Vamos dar uma olhada na função simples sendMessage . A lógica de implementação não é relevante para nós.


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


Quando a definição da função é bastante simples, a função aceita alguns parâmetros de um tipo diferente. Se forem primitivos como strings ou números, tudo é legível.


Digamos que você queira passar algumas informações adicionais junto com o conteúdo de sua mensagem para a função sendMessage .


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


Como você pode ver, o TypeScript permite que você escreva uma definição de tipo embutida para o objeto de message que deseja passar sem especificar o tipo usando a palavra-chave type ou interface .


Vamos adicionar Destructuring. Quando você passa um grande objeto de message para sua função, o TypeScript permite separar os argumentos passados para reduzir o padrão de código da variável de message repetida muitas vezes.


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


Por que acho que é uma má ideia e como você pode torná-la melhor?

Pode parecer uma boa ideia, afinal não é preciso escrever message vezes, certo? Acontece que não é tão bom. Vamos falar sobre 5 razões pelas quais eu acho que é um antipadrão.


1. Você não tem certeza de onde vêm seus dados

Ao ler o corpo da função, você vê senderId e precisa verificar novamente para ter certeza de onde essa função vem. É passado como um argumento ou calculado em algum lugar da função?


2. É difícil escrever documentação

Não há lugar natural para escrever comentários de documentação quando todos os tipos são limitados pela desestruturação na definição da função. Você pode escrever comentários entre cada campo de tipo, mas isso torna toda a definição da função ainda mais longa. Está ativamente desencorajando você a escrever um resumo rápido dos dados que está passando.


3. É difícil passar esses dados adiante

Quando seus dados são desestruturados, você precisa estruturá-los novamente em um novo objeto se quiser passá-los adiante. Isso desencoraja a criação de funções auxiliares menores e a dependência da composição para construir a lógica da função principal.


4. Você não pode reutilizar tipos de argumentos fora desta função

Se você precisar reutilizar seus argumentos de função em funções auxiliares ao compor sua lógica de função principal, deverá digitar o mesmo conjunto de tipos repetidamente. Isso torna mais fácil não escrever tipos.


5. É preciso muito espaço

Vamos encarar. São apenas muitas linhas de código que ocupam muito espaço na tela. Além disso, ele se concentra nos detalhes da implementação – o tipo interno dos argumentos que você está passando para uma função, que na maioria das vezes não é relevante quando você está olhando para essa função.


Basta criar um tipo para ele

Extrair o tipo e colocá-lo logo acima da função o torna muito mais legível. Há um local para comentários de documentação, você pode reutilizar esse tipo em alguma outra função auxiliar e alterar a definição de tipo em um local, se necessário.


 /** * 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 }


Recursos

Encontre uma lista de recursos que usei ao pesquisar esta postagem no blog: