TypeScript

Estou trabalhando há 10 meses em um projeto interessantíssimo que usa somente TypeScript, e acho que seria legal contar pra vocês como tem sido. Eu já tinha usado TS pra pequenas coisas no passado, e até então minha opinião era de que ele ajudava tanto quanto atrapalhava. A minha opinião mudou. Em um projeto de tamanho considerável o TS tem ajudado muito. Sim, ele traz um overhead, mas compensa de longe o trabalho a mais que demanda.

Pra mim, que venho de projetos maiores usando CoffeeScript, que eu adoro, foi uma surpresa e tanto. Peguei recentemente um projeto de CoffeeScript pra manter, e a falta das garantias que o compilador do TypeScript me dá foi sentida.

Os prós e contras que tenho visto, resumidamente.

Prós:

  • Pequenas refatorações com suporte da ferramenta. Renames, por exemplo, funcionam perfeitamente.
  • Grandes refatorações sem medo.
  • Uso de evoluções do EcmaScript que só virão no futuro ou ainda não foram amplamente adotadas, como EcmaScript 2015, ou além, já disponíveis hoje. Exemplo: classes, interpolação de strings, annotations, etc.
  • Autocomplete (intelisense) funcionando perfeitamente.
  • Sistema de módulos muito bem desenvolvido.
  • Paridade com a sintaxe do JavaScript. Muito melhor do que o CoffeeScript nesse sentido, o código é sempre quase idêntico.
  • Debug e source maps funcionam muito bem.

Contras:

  • Setup inicial é mais complicado do que seria com um projeto somente JavaScript. E um pouco mais do que de CoffeeScript também, mas não muito.
  • Necessidade de manter um outro gestor de pacotes para a definição de tipos (.d.ts).
  • Necessidade de compilar o projeto antes de rodar. O mesmo problema existe em um projeto de CoffeeScript, ou qualquer outro transpiler.

O setup do projeto

É um projeto de ASP.NET 5, que começou ainda nos alphas, e vem atualizando desde então. A parte de TypeScript, no entanto, é completamente independente dessa tecnologia. A verdade é que o ASP.NET 5 é que funciona melhor com front end do que sua versão anterior.

Adotamos commonjs para o sistema de módulos, com apoio do Browserify para rodar no front end. Como o NodeJS é ferramenta fundamental de desenvolvimento de frontend hoje, e ele também trabalha com commonjs, é possível testar todo o código usando o Node. Adotamos o mocha como framework de testes, seguido de sinon e chai, um setup de testes bem comum no mundo de Node. O JSDOM faz o trabalho de emular o DOM do browser, e tudo funcionou perfeitamente. O Istanbul resolve a cobertura de código.

É um projeto com angular, e jquery, e fomos capazes de testar inclusive interações e alterações com o DOM. Já usei ZombieJS no passado, mas é difícil superar o suporte do JSDOM hoje em dia. Ainda estamos no Node 0.12, mas ansiosos para ir para o 4.0, o que deve acontecer nas próximas semanas. Usamos Npm 3 (atualmente 3.3), que resolve bem o problema de caminho muito longo no Windows e já está bem estável. O npm 2 aninha dependências por padrão e estourava o limite de 255 caracteres do path do Explorer do Windows. O Node no Windows está super estável, não tenho do que reclamar. Compilação/testes/linting/watch/etc são gerenciados pelo Gulp.

O que eu tenho adorado

Algumas features do Typecript são realmente muito legais. Destaco algumas:

  • Classes mantém o código mais limpo e fácil de ler, quando o objetivo é de fato criar um objeto em runtime.
  • Interpolação de strings! <3
    var str = `Um valor: ${valor}`;
  • Retorno múltiplos valores de métodos, por exemplo:
    var [ um, dois ] = obterValores();
  • Possibilidade de destruturar um objeto no retorno de um método:
    var { um, dois } = obter();
    function obter() {
    return { um: 1, dois: 2, tres: 3 };
    }
  • Possibilidade de importar somente um pedaço de um módulo, via também via desestruturação:
    import { pedaco } from ‘./modulo’;
  • Valores default num método:
    function metodo(a:int = 0) { }
  • Parâmetros “Rest”, semelhante ao “params” do C#:
    function metodo(…valores){ }
    metodo(1, 2, 3);
  • Possibilidade de exportar automaticamente um valor a partir de um módulo. Pr exemplo, em um mesmo arquivo de código:
    export class A { }
    export var b = 1;
  • Foreach!
    for (var x of xs) { console.log(x); }
  • Enums que viram números (const enums).
  • Tipagem opcional: já movimentei muito código, e erros, como a remoção de um parâmetro ou a mudança de um tipo de retorno de um método, foram pegos antes mesmo de eu rodar os testes.

O que você precisa fazer para o Typescript não te atrapalhar

Algumas dicas valiosas pra te ajudarem a não odiar um transpiler em geral e o TS em particular:

Utilize um gestor de tarefas, idealmente Gulp ou Grunt. Eles vão te poupar muito tempo. E o Visual Studio 2015 suporta tanto Gulp quanto Grunt, rodando suas tarefas quando o projeto abre, por exemplo, ou quando você compila, etc.

Use e abuse do TSD. Não há nenhuma outra opção viável quando o assunto é gestão de tipos de dependências do TS. Mas não dependa só dele. Algumas bibliotecas estão desatualizadas ou incompletas. Quando encontrar uma assim, complete a tipagem no seu projeto, teste por um tempo, e depois submeta um pull request ao DefinitelyTyped.

Utilize um mecanismo de watch no seu gestor de tarefas, assim, sempre que alterar algum código e salvar, ele será automaticamente compilado. Isso evita que você tenha que ficar voltando pra linha de comando.

Aprenda a não tipar tudo. Não é porque o TypeScript permite tipar tudo que você deve. De vez em quando faz bem usar os atributos dinâmicos da linguagem.

Não use classes pra tudo. TypeScript é JavaScript, e JavaScript não é uma linguagem estruturada para depender somente de classes. JavaScript tem uma natureza muito funcional, faça uso dela. Por exemplo, você pode criar uma diretiva do angular com uma classe, mas não deve, porque ela não encaixa como deveria. Use uma função e seja feliz.

Crie um arquivo de projeto (tsconfig.json). Ele vai te ajudar muito no VSCode e/ou no Visual Studio e também na compilação.

Se você quer modelar um objeto, mas somente a estrutura, use interfaces, não classes. Classes tem que ter comportamento, e o TypeScript suporta tipagem estrutural, ou seja, um objeto que atende a estrutura de uma interface automaticamente a implementa.

Aliás, use tipagem estrutural no lugar de interfaces quando fizer sentido. Por exemplo, o parâmetro “bar”, poderia ter uma interface, mas só o que me interessa é o método “raise”, então, expresse isso:

function foo(bar:{raise:()=>number}) {
    let i = bar.raise();
} 

Utilize o Playground pra testar rapidamente algum código (já que até hoje não temos um REPL oficial). Ou uso o TSUN, que não é um REPL perfeito mas quebra um galho.

Conclusão

São pequenos detalhes, mas que fazem muita diferença no dia a dia. No começo do projeto eu estava em dúvida se a decisão de usar TypeScript realmente seria a melhor pro projeto. Hoje não tenho mais dúvida, tem valido muito a pena.

O interessante é que parte do time sequer usa o Visual Studio Full pra escrever TypeScript. O suporte do Visual Studio Code tem sido também fantástico. E todo o projeto pode rodar num Linux ou Mac sem maiores problemas.

Vamos começar agora a olhar pro language services do TS para avaliar algumas features semelhantes a analisadores, que temos no C#. E já estamos no TypeScript 1.5, e de olho na saída do 1.6, que já está em beta.

E você, tem usado TypeScript? O que tem achado?

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.