Typescript

A Microsoft lançou o Typescript semana passada. É uma versão alpha ainda. Em poucas palavras ele é um superconjunto do Javascript, que adiciona tipagem e mais algumas coisas. Por esse motivo todo código JS é também código TS.

Não vou nesse post explicar o que é o TS, veja o post do Soma a respeito, assista o vídeo do Anders Hejlsberg, acesse o site da linguagem, e veja o código fonte (ele é open source). Brinque um pouco com ele no playground também, é bem divertido (permite que você escreva código TS, já veja o JS gerado, e até o rode). Feito isso, volte aqui. Vai te tomar umas 3 horas mais ou menos, no mínimo, pra passar por todos os recursos. Se não der tempo, ao menos leia o post do Soma.

Nesse post quero falar do que achei da linguagem, e os pontos fracos e fortes que vi. É uma análise inicial, ainda tenho mais coisas a dizer.

Achei o esforço positivo. Não sei se todos perceberam, mas a Microsoft não está tentando acabar com o Javascript (ele não é um Dart). O objetivo deles é facilitar o desenvolvimento com Javascript. Eles sentiam falta de um bom ferramental para escrever aplicações grandes (note como em todo lugar eles falam de “application-scale Javascript”), e há um limite de até onde eles conseguiriam ir com uma linguagem dinâmica quando o assunto é ferramental. Coisas como refatorações, e navegação no código ficam mais difíceis nesse cenário (algo que programadores de Javascript, Ruby, Python, estão acostumados a vivenciar). Sentiam falta de organização do código também, então introduziram a ideia de módulos. E sentiam falta de classes para tornar o desenvolvimento mais fácil e intuitivo (que afinal gosta de prototypes?).

Pra deixar claro que não estão tentando levar os tipos ao JS, toda a tipagem escrita no Typescript é apagada no Javascript gerado. Isso é bem legal.

Minha impressão é que a linguagem está sendo criada por um motivo velado, pouco discutido. Me parece que o principal objetivo é suportar aplicações do Windows 8. No entanto, o marketing não é esse, a Microsoft tem dito que o foco é suportar suas próprias aplicações, e também as do mercado.

Eu gosto muito da ideia de todo JS já ser também um código TS. Facilita muito a transição. Quem já lidou com SASS sabe como isso é importante, já que SASS é totalmente compatível com CSS. Você pode simplesmente pegar um código JS e jogar em um arquivo .TS e sair adaptando o que quiser. Não precisa fazer uma migração do seu código. E quem está usando CoffeeScript sabe que não é divertido converter código (mas pra isso existem ferramentas, como o JS2Coffee).

Gostei também que os tipos são opcionais. Você não é obrigado a tipar tudo, o que dá toda a liberdade que quiser, e você usa tipos também só onde quiser.

Gostei da ideia de interfaces abertas. Eles fizeram um excelente trabalho nesse ponto, modelando perfeitamente para um tipo estático o que o dinâmico permite. Note por exemplo, o que fizeram com o jQuery e o jQueryUI. Você tem o $().draggable, presente no jQueryUI, que alterou de fato a interface do jQuery. Assim, você tem a interface jQuery definida (veja o código fonte original aqui):

interface JQuery {
    /****
     AJAX
    *****/
    ajaxComplete(handler: any): JQuery;
    ajaxError(handler: (evt: any, xhr: any, opts: any) => any): JQuery;
    ajaxSend(handler: (evt: any, xhr: any, opts: any) => any): JQuery;
    ajaxStart(handler: () => any): JQuery;
    /* mais código omitido*/
}

 

Já no arquivo de definição do jQueryUI, a interface é aberta e recebe alguns complementos (veja original aqui):

interface JQuery {
    draggable(options: Draggable): JQuery;
    draggable(optionLiteral: string, options: Draggable): JQuery;
    draggable(optionLiteral: string, optionName: string, optionValue: any): JQuery;
    draggable(optionLiteral: string, optionName: string): any;
    // draggable(methodName: string): any;
    droppable(options: Droppable): JQuery;
    droppable(optionLiteral: string, options: Draggable): JQuery;
    droppable(optionLiteral: string, optionName: string, optionValue: any): JQuery;
    droppable(optionLiteral: string, optionName: string): any;
    droppable(methodName: string): any;
}

 

Não gostei do suporte a AMD. Na verdade, AMD não funciona, pelo menos diretamente. Toda sintaxe de import/export presente no Typescript é inútil com AMD, ele simplesmente não gera o código esperado. Por outro lado, o suporte ao CommonJS é perfeito. No entanto, concordo plenamente com os argumentos do autor do RequireJS em onde o CommonJS falha. Pra mim esse é um problema grave, e enquanto não resolver não posso usar Typescript. Qual comportamento exatamente eu precisaria? Precisaria que o seguinte código funcionasse:

/// <reference path="node.d.ts" /> 
import http = module("http")
class MyServer {
    create(port, message){
        http.createServer((req, res) => {
            res.writeHead(200, { "Content-type": "text/html" });
            res.write("<h1>" + message + "</h1>");
            res.end();
        }).listen(port);
    }
}
return MyServer;

Mas ele não compila. A última linha é um problema. Ao rodar no terminal, recebo a seguinte mensagem:

C:/ts/server.ts (12,7): return statement outside of function body

Preciso ser capaz de definir um módulo que retorna um tipo, e até agora não consegui. Por exemplo, nesse código:

import m = module("./mamifero");
export class Macaco extends m.Mamifero {
    pula(){
        console.log("pulou");
    }
}

Não consigo fazer com que o módulo mamífero retorne um tipo newable. Sou obrigado a herdar de m.Mamifero. Se tentar herdar direto de mamífero, recebo esse erro:

C:/ts/Macaco.ts(1,0): Types may not be derived from module types

Gostei muito também que o TS já vem com source mapping. Isso melhora muito a qualidade de debug, já que um erro no JS vai mapear diretamente para o TS. Veja um exemplo aqui. Ter source mapping já na versão 0.8 (atual) demonstra claramente a ideia da Microsoft, de fazer uma linguagem que permita um ferramental melhor. Pra termos de comparação, o CoffeeScript está na versão 1.3.3, já tem 3 anos de vida, e só agora na versão 1.4 vai ter source mapping.

O MIguel de Icaza faz um comentário interessante sobre o Typescript: de pouco adianta ter uma linguagem capaz de entregar ferramental superior, se esse ferramental é só o Visual Studio. Ele argumenta que metade da Web é feita em/para Unix/Linux, e esses caras desenvolvem com Mac/Linux. Enquanto não houver um bom bundle/plugin/extensão para TS que suporte Eclipse, VIM, Emacs, etc, essas ferramentas entragarão, no máximo, syntax highlighting. É o que temos até agora. É um argumento bastante pertinente, e pode acabar isolando o TS apenas no mercado que a Microsoft atua, o que é restrito quando se fala de toda a web.

E por falar nisso, eu testei o suporte para Sublime, VIM e Visual Studio. Sublime funciona perfeitamente, mas é meio chato de instalar. VIM não funcionou, fui obrigado a puxar um bundle de outra pessoa (meu bundle de VIM está no github, BTW). No Visual Studio também não funcionou. Instalei a ferramenta, mas nada mudou. Tive que ir até “C:\Program Files (x86)\Microsoft SDKs\TypeScript\0.8.0.0”, e rodar o “TypeScriptLanguageService.vsix” na mão pra ele funcionar. A extensão do VS Web Essentials 2012 ajuda também por exibir o arquivo compilado lado a lado, recomendo!

Em geral, o que tenho visto até agora tem sido insuficiente deixar de lado a minha linguagem preferida que compila para JS: CoffeeScript. Depois vou fazer uma comparação entre as duas, mas adianto que o tipo estático tem acrescentado um overhead desnecessário, e tal overhead não banca o esforço extra que senti tipando o código. Além disso, CS é bem mais enxuto e bonito, removendo a cerimônica excessiva do JS. Não deixa de soar como um esforço do Anders para tentar tornar o JS algo que ele não é, por causa do seu amor à tipagem estática. Nesse sentido, o CS abraça melhor a causa. Fica bem claro que TS em geral encaixa melhor na cabeça de quem está acostumado à linguagens estáticas como Java e C#, enquanto CS é mais fácil pra quem está acostumado com linguagens dinâmicas como Python, Ruby, e… Javascript!

Não gostei da argumentação de que tipos estáticos promovem um desenvolvimento mais seguro. Quando falamos de segurança e qualidade, tipagem é só mais um tipo de teste. Aplicações complexas tem que ter testes cobrindo o Javascript, e se tais testes existem, a existência ou não do tipo faz pouca diferença. Lógico que no caso da refatoração o caso é diferente, a tipagem ajuda, e muito.

Tenho brincado bastante com o TS, e vou começar a postar os resultados interessantes no Github. Criei um repositório lá só pra isso. Os exemplos deste post estão lá.

No próximo post vou comparar o Typescript com o Coffeescript e fazer minhas considerações. Esse foi só um post para comentar minhas primeiras impressões.

E vocês, o que acharam?