← Ir a portada

Un vistazo a TypeScript

Durante este fin de semana (y parte de la semana) he podido jugar con la KataTennis en TypeScript Un lenguaje creado por Anders Hejlsberg creador de Pascal, Delphi y C#.

Así que aprovechando el código de la Katatennis, veamos que nos trae TypeScript.

Características Básicas de TypeScript

Tipado En Diseño

TypeScript es un lenguaje que añade a JavaScript una capa de tipado estático y algunas otras incorporaciones de OOP tradicional. Esta capa puede resultarnos de muchísima ayuda durante el desarrollo. Sin embargo todas estas características son simplemente para ayudar a trabajar con JavaScript en tiempo de diseño, ya que TypeScript compila todo como JavaScript tradicional, veamos un ejemplo:

DoScoring(currentScore: number, otherPlayerScore: number, message : ScoringMessage): ScoringRuleResult

En el código anterior hemos indicado el tipo de cada uno de los parámetros a TypeScript y tipo que tendrá resultado de la función. Esto permite al compilador de TypeScript avisarnos en caso de pasar un tipo incorrecto. También, dado que TypeScript entiende los parámetros de una función como obligatorios, nos ayuda cuando omitimos por error alguno de los parámetros.

Lo mismo es posible cuando definimos un parámetro de función, TypeScript permite que definamos su forma utilizando una sintaxis muy parecida a la utilizada en C# para las expresiones lambda:

DoSomething(whatToDo : (s : string) => bool);

Por supuesto, el tipado es elección del desarrollador, en todo momento podemos no especificar el tipo de una variable o parámetro o utilizar la plabra clave any. De la misma forma, podemos marcar un parámetro en una función como opcional, tan sólo especificando ? después del nombre.

Clases y Herencia tradicional

TypeScript implementa clases y herencia basados en la OOP tradicional. Esto permite crear clases como:

class Match {
    private alreadyWinner = false;
 
    constructor (public player1: Player, public player2: Player, public scoreboard: Scoreboard) {
        if (!player1) throw "Player1 Is Required";
        if (!player2) throw "Player2 Is Required";
}
 
class TennisMatch extends Match {
    constructor (player1, player2) { 
        super(player1, player2, new TennisScoreboard());
    }
}

Match es una clase tradicional en la que hemos definido un constructor con 3 parámetros. También tiene una variable privada, que como todo en TypeScript sólo es privada durante el tiempo de diseño, ya que JavaScript no tiene dicha accesibilidad.

Podemos aplicar herencia utilizando extends, TypeScript nos obligará a llamar al constructor de la clase padre mediante super, y nos ayudará en los parámetros necesarios. Realmente sencillo.

Interfaces y Tipado Estructural

JavaScript no permite definir el tipo concreto de un parámetro en una función. Sin embargo, esta característica nos permite pasar cualquier parámetro que cumpla estructuralmente con el tipo que esperamos.

TypeScript respeta el Tipado Estructural, a la vez que nos ayuda en tiempo diseño con el primer punto.

private ScoringOnAdvantageWins(currentScore: number, otherPlayerScore: number, message : ScoringMessage): ScoringRuleResult {
    var result = false;
 
    if (result = (currentScore == Scoreboard.advantage)) {
        currentScore = Scoreboard.win;
        message.message = "wins";
    }
 
    return { currentScore: currentScore, otherPlayerScore: otherPlayerScore, satisfied: result };
}

Aqui utilizando la notación de objetos de JavaScript, creamos un objeto ScoringRuleResult. TypeScript nos ayuda a inicializar cada uno de los miembros con información sobre su nombre y tipo, gracias a que previamente hemos definido la interfaz de ScoringRuleResult:

interface ScoringRuleResult {
    currentScore: number;
    otherPlayerScore: number;
    satisfied: bool;
};

Referenciando otras librerías

Realizar una Kata sin TDD no sería lo mismo. En JavaScript existen muy buenas y extendidas librerías para hacer TDD, aunque mi favorita es Jasmine.

Aunque en TypeScript podemos incluir código JavaScript sin modificaciones, cuando la complejidad del código es muy grande, podemos encontrarnos con errores. Al menos en esta versión 0.8.0.0 de TypeScript Jasmine no podía incluirse como una referencia dentro de un fichero de TypeScript.

Así que TypeScript dispone de un método con el que hacer referencia a librerías de JavaScript sin que afecte a la compilación y, sobre todo, con información sobre el tipo y forma de la API a utilizar. TypeScript incluye archivos de definición para JQuery, WinJS o el DOM de HTML, sin embargo todavía no hay uno para Jasmine. Así que siguiendo la documentación podemos crear la definición de una API como Jasmine que luego podremos referenciar en nuestros archivos de TypeScript:

declare function describe(suiteName : string, suite : () =>; void);
declare function xdescribe(suiteName : string, suite : () =>; void);
 
declare function it(expectation: string, assertion: () =>; void );
declare function xit(expectation: string, assertion: () =>; void );
 
declare function beforeEach(action: () =>; void );
declare function afterEach(action: () =>; void );
 
interface JasmineMatchers { 
    not: JasmineMatchers;
    toBe(match: any);
    toEqual(match: any);
    toMatch(match: string);
    toBeDefined();
    toBeUndefined();
    toBeNull();
    toBeTruthy();
    toBeFalsy();
    toContain(match : any);
    toBeLessThan(match: number);
    toBeGreaterThan(match: number);
    toBeCloseTo(expected: number, tolerance: number);
}
 
declare function expect(actual: any): JasmineMatchers;

Intellisense With Jasmine

Depurando: SourceMapping

Podemos depurar TypeScript mediante el JavaScript generado por el compilador, o podemos utilizar la técnica SourceMapping. Sourcemapping esta soportado en las últimas versiones de desarrollo de Chrome y Webkit, y nos permite depurar en el navegador el código compilado en JavaScript, pero viendo TypeScript.

El compilador de TypeScript soporta generar archivos SourceMap mediante el parámetro –sourceMap:

tsc --sourcemap hello.ts

También podemos modificar la siguiente línea añadiendo el parámetro –sourcemap en nuestro fichero de proyecto de Visual Studio y disfrutar de SourceMapping automático para todo el proyecto:

<Target Name="BeforeBuild">
    <Exec Command="&quot;$(PROGRAMFILES)\Microsoft SDKs\TypeScript\0.8.0.0\tsc&quot; -sourcemap @(TypeScriptCompile ->'&quot;%(fullpath)&quot;', ' ')" />
  </Target>

Una vez activado el SourceMapping en Chrome, podemos depurar nuestro código TypeScript directamente en el navegador:
Depurando en Chrome una spec de Jasmine

Valoración

TypeScript se añade a la ya sobrecargada lista de lenguajes que compilan a JavaScript, una moda que en estos momentos ha alcanzado toda su fuerza. Sin embargo, la aproximación de Anders me ha gustado. La idea de describir en diseño cuál es la información de tipo pero permitiendo ser dinámicos cuando se necesita.

Aún así hay que advertir, que no es recomendable programar en TypeScript sin antes conocer la programación en JavaScript, dado que sin conocerlo nos podríamos encontrar con situaciones extrañas durante el desarrollo, a las que sólo podemos encontrar sentido si conocemos como funciona JavaScript.

Teniendo en cuenta que TypeScript esta en su versión 0.8.0.0 le queda un largo camino por recorrer, para convertirse en un lenguaje maduro, pero sin duda es un buen comienzo.

Enlaces

Specificación en TypeScript de Jasmine
Solución a la KataTennis en Solveet

Apuntes relacionados:

2 Respuestas a “Un vistazo a TypeScript”

  1. Nota histórica:
    el autor de Pascal es Niklus Wirth.

    Según wikipedia Heljsberg creo Turbo Pascal.

  2. Iñaki Elcoro dice:

    Gracias por la aclaración Antonio, con Pascal me refería precisamente a esa versión de Turbo Pascal.

    Saludos,

Deja un comentario