Typescript: Nem Tudo São Flores

Cover image

Esse artigo e uma tradução livre para português autorizada pelo autor Kris Guzman, se você gostou não deixe de ir ao artigo original (em inglês) e deixar sua curtida.

Caso encontre algum erro, pode entrar em contato através do meu email.

Introdução

Antes de tudo, me deixe ser claro:

Javascript tipado e fantástico! Eu venho utilizando Flow e continuarei usando Typescript agora, e com o passar do tempo. É uma ferramenta poderosa e vem crescendo rapidamente.

Porém, qual é o custo desse poder? Quais são as desvantagens que podem mudar o jogo?

Às vezes nós precisamos parar para avaliar as ferramentas que usamos para que possamos ver os prós e contras. Então, deixando de lado a emoção. Vamos avaliar os contras do Javascript tipado.

Um Simples Código Fica Verboso

Como mencionado, Minha perspectiva e principalmente vindo da utilização de React + Redux. Dependendo do que você usa a sua experiência pode ser diferente.

Em geral, a ironia de usar Flow e Typescript e que a tipagem manual e o mais queremos evitar! Isso pode deixar o código mais verboso, propenso a erros e difícil de dar manutenção.

No mundo ideal, nós deixamos o Typescript dar dicas dos tipos nas nossas bibliotecas e as já definidas na linguagem. Dessa forma, temos o benefício da tipagem dar segurança e então precisamos apenas gerenciar os tipos criados de forma personalizada.

Só que às vezes não tem como evitar a verbosidade. Vamos ver um exemplo de um simples componente em React baseado em classe, escrito em Typescript:

interface NameProviderProps {
  children: (state: NameProviderState) => React.ReactNode;
}
 
interface NameProviderState {
  readonly name: string;
}
 
export class NameProvider extends React.Component<NameProviderProps, NameProviderState> {
  readonly state: NameProviderState = { name: 'Piotr' };
 
  render() {
    return this.props.children(this.state);
  }
}

Agora veja o mesmo componente em Javascript:

export class NameProvider extends React.Component {
  state = { name: 'Piotr' };
 
  render() {
    return this.props.children(this.state);
  }
}

A versão escrita em Typescript tem 248% a mais de código. Sim, props e state estão claramente definidos, mas será se isso e realmente o que podemos chamar de legível atualmente?

Dê uma olhada nesse exemplo para lidar com ações no redux. É muito bem pensado e útil, eu recomendo a leitura, mas é realmente necessário?

type InferValueTypes<T> = T extends { [key: string]: infer U } ? U : never;
type Actions = ReturnType<InferValueTypes<typeof actions>>

Muitas Bibliotecas Não Possuem @types

Mesmo com o ecossistema do Javascript tipado crescendo, ele está longe de 100% de cobertura. Isso quer dizer que você continua adicionando tipos manualmente em vários casos.

Ainda assim, todo grande projeto acaba adicionando alguns tipos personalizados não tão bem pensados (ou acaba copiando de alguma issue do Github) para se ajustar com algumas bibliotecas ou casos de uso.

Até mesmo as bibliotecas mais populares como o Redux, podem ser um caos para gerenciar actions, thunks etc.

Tipos Escritos Manualmente são mais Propensos a Erros

Vamos imaginar que uma grande equipe está trabalhando em um projeto e João escreve a seguinte definição de tipo:

type PropsA = { 
  name: string, 
  date: Date, 
  url: string 
}

Enquanto essa definição de tipo era criada, Maria não percebeu que ela existia. Então foi e criou um tipo parecido:

type PropsB = { 
  name: string, 
  date: string, 
  url: string 
}

Agora temos tipos redundantes, e ainda pior, PropsB está definida um pouco diferente. A promessa de definição clara de tipos vai por água abaixo.

Isso não é um cenário hipotético que raramente ocorre. Eu já vi isso acontecer em grandes projetos com milhões de dólares investido.

Dá Uma Falsa Sensação de Segurança

Embora essa possa não ser a melhor maneira de fazer isso, digamos que você definiu uma redux action da seguinte forma:

export const MY_BASIC_ACTION:MY_BASIC_ACTION=MY_BASIC_ACTION

Com apenas alguns é fácil, mas quando você começa a ter por exemplo umas 30 actions, a seguinte situação pode ocorrer com muita facilidade ao copiar uma ação antiga como modelo para uma nova:

export const MY_NEW_ACTION:MY_BASIC_ACTION=MY_BASIC_ACTION

Consegue ver o problema? Acabamos de definir uma nova action igual a primeira.

É extremamente difícil de identificar porque você irá dar um dispatch MY_NEW_ACTION, mas na verdade será MY_BASIC_ACTION.

Você irá se sentir tão seguro e confuso com Flow e Typescript que irá ficar batendo a cabeça por horas até perceber que é apenas um problema de tipagem!

O Gerenciamento de tudo isso é uma Habilidade em Si

Javascript em si já é complicado de entender. Quando você adiciona tipagem a uma linguagem dinâmica, e preciso grande habilidade para escrever os tipos de forma correta e produtiva.

Isso não é de fato uma desculpa para evitar Javascript tipado. Mas é algo a se analisar para projetos no mundo real e com prazos apertados ou um grande número de desenvolvedores júniors.

Na maioria das vezes, você irá tipar properties, state, etc. No entanto, uma hora chega o dia em que você precisa fazer algo com tipagem fraca.

Mais Configurações para Gerenciar

Configurar um ambiente com Typescript/Flow não é tão simples. Você irá usar ferramentas para build, gerenciar arquivos de configuração, criar mais dependências etc.

As bibliotecas que antes eram fáceis de integrar agora apontam para um local separado apenas para funcionar junto com o TypeScript.

Você gastará muito mais tempo procurando soluções nas issues do GitHub tentando fazer a Biblioteca “X” funcionar com o Flow ou o TypeScript. Isso pode ser uma pedra no sapato.

Uma boa IDE pode ser tudo que Você Precisa

O IntelliSense no VSCode junto com ESLint oferece muitos dos benefícios que os desenvolvedores buscam no Typescript e no Flow.

Na boa, veja o quão longe você consegue chegar apenas com sua IDE ajudando. Aposto que você irá ficar surpreso com o pouco de falta que o Typescript irá fazer você sentir (mas sempre sentirá pelo menos alguma coisa).

Codando sem o conforto e segurança que a tipagem lhe dá, irá dar a você todo o poder do Javascript, afinal é uma linguagem de tipagem fraca, e mantém você mais atento ao código que você escreve.

Conclusão

Um projeto feito sem tipagem que ainda é bem documentado é uma grande conquista. Pode parecer que odeio o Typescript, mas isso está longe de ser verdade. Adoro o Typescript e sei seus benefícios. No entanto, é importante ter uma conversa sobre seus lados negativos.

No final das contas, trata-se de usar a melhor ferramenta para se trabalhar, certo?