Skip to content

Instantly share code, notes, and snippets.

@BlueSlimee
Last active January 4, 2023 01:42
Show Gist options
  • Save BlueSlimee/c2fa2416a94f09eeb8014a64139bafda to your computer and use it in GitHub Desktop.
Save BlueSlimee/c2fa2416a94f09eeb8014a64139bafda to your computer and use it in GitHub Desktop.
não use ts

TypeScript vale a pena?

TypeScript extends JavaScript by adding types.

By understanding JavaScript, TypeScript saves you time catching errors and providing fixes before you run code.

Parece tentador, não? Só que se você já usou TypeScript, você sabe que não é bem assim. O TypeScript pode até "ajudar" em projetos grandes, mas no final, só atrapalha. Vou explicar o por quê.

Sem checagem de tipos em runtime

O TypeScript não faz checagem de tipos em runtime. Isso significa que, se alguma coisa que era para ser X acaba sendo null durante a execução, o TS nem percebe (no TS). Isso pode não parecer muita coisa até você tornar sua aplicação pública. Se alguma coisa que era para ser de tipo X acaba sendo null, sua aplicação vai cair, já que você vai provavelmente tentar realizar alguma operação com base nesse valor, jogando toda a "segurança" do TypeScript contra a parede.

"Ah, mas e se eu colocar if (!valor) ...?" Aí obviamente vai ficar seguro. Mas se pergunte, vale a pena usar uma ferramenta que mal funciona e ter que fazer o trabalho dela (type checking). Vale?

Vai contra os princípios do JavaScript

Em 1994, Brendan Eich foi contratado pela Netscape para criar uma linguagem para manipular o conteúdo de sites de maneira dinâmica, assim surgindo o JavaScript (LiveScript na época). Viu esse "de maneira dinâmica"? Esse é um dos principais benefícios e conceitos do JavaScript. Você pode alterar valores em runtime, remover valores, criar objetos sem factories. Essa é a magia da língua. Aí vem a Microsoft e decide que isso é errado e decidem refazer tudo (como fizeram com o JavaScript na época). Até aí ok, dá até de entender. O problema? O negócio mal funciona. Vou dar de exemplo o código abaixo:

function fazerAlgo(): Promise<Lista[]> {
  return new Promise(async (resolve, reject) => {
    try {
      const resultado = await fazerRequest()
      resolve(resultado.data as Lista[])
    } catch (e) {
      reject(`Erro: ${e.message}`)
    }
  })
}

Se você prestar atenção, você pode ver que a função retorna apenas um tipo: Promise<Lista[]>. Entretanto, no reject() estamos retornando uma string. Sendo assim, esse código não compila. Certo? Errado.

Esse código compila! Isso mesmo, estamos retornando um tipo complemente errado e ainda sim funciona. Tudo de bom, né?

Causa overhead em relação ao JavaScript

Essa aqui o povo odeia que fale: TypeScript deixa seu código mais lento sim, e é bem lógico. Vamos analisar o seguinte trecho de código em TypeScript:

class Bicicleta {
  posicao = 0

  andar () {
    this.posicao++
  }
}

É uma simple classe, com uma propriedade e um método. Nada de mais. Agora, quando você transpila para JavaScript... esse é o resultado:

"use strict";
var Bicicleta = /** @class */ (function () {
    function Bicicleta() {
        this.posicao = 0;
    }
    Bicicleta.prototype.andar = function () {
        this.posicao++;
    };
    return Bicicleta;
}());

Ainda assim, nada de mais. Classes do ES6 são apenas syntax sugar para esse esquema de prototype. O problema vai começar mesmo quando você ter que debugar esse código. Você vai ter que ler cada parte desse lindo output. Mas se você acha que para por aí, tá enganado! Fica ainda mais bonito se você usar outras funções do ES6 (ou funções de outro target maior do que você selecionou na sua tsconfig.json). Ou seja, ele vai encher seu código de polyfill quando você tem módulos nativos a sua disposição.

"É, mas isso não tem nada a ver com performance!!!" Ah, é? Vamos ver então. Vamos fazer o teste com a classe da bicicleta. Não tá chamando nenhuma função, nem fazendo nada do tipo. Vamos ver quem é mais rápido.

Primeiro, vamos compilar o código e executar logo em seguida.

$ time tsc && node dist/index

real    0m5.184s
user    0m8.753s
sys     0m0.273s

5 segundos. Performance astronômica, eu diria. Agora vamos executar o código direto no node, sem compilar (isso mesmo, o código da bicicleta funciona sem problema algum direto no node).

$ time node src/index.ts

real    0m0.327s
user    0m0.303s
sys     0m0.023s

Levou 327ms. Isso mesmo, nem metade de um segundo demorou.

"Ah, mas não é justo!! Se compilar obvio que vai demorar!" Então vamos executar o resultado ao invés de compilá-lo e executar.

$ time node dist/index.js

real    0m0.666s
user    0m0.380s
sys     0m0.080s

Levou o dobro do tempo. Não parece muita coisa, mas conforme mais complexo o projeto vai ficando, pior a performance fica. E isso é porque só definimos uma classe. Não a chamamos nem nada do tipo.

"Ah, você tá usando o target errado hur dur polyfill hur dur" Então vamos usar ES6 como o target.

$ time node dist/index.js

real    0m0.492s
user    0m0.373s
sys     0m0.047s

200ms mais lento. Oops.

Quem usa TypeScript?

A Google e a Microsoft (criou o negócio, faz sentido usarem). O resto são startups apostando em novas tecnologias. Por que? Não sei, não encontrei nada sobre.

Conclusão

TypeScript pode parecer útil, mas no final do dia, ainda é JavaScript. Ainda é uma linguagem de natureza dinâmica, apesar das falhas tentativas de colocar tipos nela. Fazer isso quebra os princípios básicas do JavaScript, que é ser dinâmico. A única coisa que ele pode ajudar em grandes projetos, mas vale a pena perder performance e usar modificações que trocaram conceitos base do JavaScript? Fica a reflexão.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment