Aplicaciones modernas en JavaScript con TypeScript

TypeScript es un lenguaje de programación moderno que permite crear aplicaciones web robustas en JavaScript. TypeScript no requiere de ningún tipo de plugin, puesto que lo que hace es generar código JavaScript que se ejecuta en cualquier navegador, plataforma o sistema operativo.

Instalación

TypeScript viene dentro del paquete de actualización de Visual Studio 2013 Update 2, se puede descargar como paquete alternativo para Visual Studio 2012. También se puede instalar en Node-js como paquete para empezar a usarlo desde la línea de comandos.

 npm install –g typescript
tsc helloworld.ts

 

Caracteristicas del lenguaje

TypeScript define varios tipos de datos extras además de los definidos en JavaScript. Cuando se hace una definición de tipo se tiene que poner un sufijo del tipo de datos en la definición, por ejemplo:

 var isDone: boolean = false;

Boolean

Number

String

var isDone: boolean = false;

var height: number = 6;

var name: string = "bob";

name = 'smith';

Array

Enum

Any

var list:number[] = [1, 2, 3];

var list:Array<number> = [1, 2, 3];

enum Color {Red, Green, Blue};

var c: Color = Color.Green;

var notSure: any = 4;

notSure = "maybe a string instead";

notSure = false; // okay, definitely a Boolean

Void

 

 

function warnUser(): void {

    alert("This is my warning message");

}

 

 

Interfaces

Una de las características principales de un lenguaje type-checking es que se enfoca en dar forma a los valores que tienen en tiempo de ejecución. Esto a veces se llama “duck subtyping”.

La mejor manera de ver cómo funcionan las interfaces es con un ejemplo:

 function printLabel(labelledObj: {label: string}) {
console.log(labelledObj.label);
}
var myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

El type-checker comprueba que la llamada a printLabel, en esa llamada hay como requisito un parámetro labelledObj que es un objeto que como mínimo tiene una propiedad llamada label, de esta manera no hay forma de definir el tipo de la llamada.

Con TypeScrip se puede definir una interfaz para ese tipo de dato para asegurarnos de que el parámetro tenga como mínimo esa propiedad definida.

 interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
var myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

Además de definir las propiedades que puede tener un objeto a la hora de ser llamado en una función, también se puede definir las funciones que deberá implementar la clase que herede de la interfaz.

Aquí se puede ver una definición de una interfaz con un método:

 interface SearchFunc {
    (source: string, subString: string): boolean;
}

Así es como se define una función que implementa esa interfaz:

 var mySearch: SearchFunc;
    mySearch = function(source: string, subString: string) {
    var result = source.search(subString);
    if (result == -1) {
        return false;
    }
    else {
        return true;
    }
}

Array Types

Lo mismo que se puede definir interfaces, también se pueden definir arrays.

 interface StringArray {
    [index: number]: string;
}

var myArray: StringArray;
myArray = ["Bob", "Fred"];

Clases

En TypeScript se pueden definir clases, que además también puede implementar las interfaces que previamente se han definido.

 interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

var cs: ClockStatic = Clock;
var newClock = new cs(7, 30);

También se puede hacer que una interfaz extienda otra interfaz, es decir que herede de ella.

 interface Shape {
    color: string;
}

interface Square extends Shape {
    sideLength: number;
}

var square = <Square>{};
square.color = "blue";
square.sideLength = 10;

Herencia de clases

También se puede definir herencia de clases definidas previamente.

 class Animal {
    name:string;
    constructor(theName: string) { this.name = theName; }
    move(meters: number) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move() {
        alert("Slithering...");
        super.move(5);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move() {
        alert("Galloping...");
        super.move(45);
    }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);

La diferencia, a simple vista con C#, es que se utiliza la palabra reservada extends para definir cuando una clase está heredando de otra.

La visibilidad de todos los miembros es pública mientras no se especifique lo contrario.

Módulos

Otras de las características de TypeScript es la capacidad de definir módulos para que la funcionad se asile y se pueda reutilizar en cualquier momento.

Los módulos se pueden definir en un fichero o en varios fichero, de manera que el mismo modulo pueda estar repartido, para tener una parte core y otras partes que se puedan modificar sin tener que modificar el fichero principal.

 module Validation {
    export interface StringValidator {
        isAcceptable(s: string): boolean;
    }

    var lettersRegexp = /^[A-Za-z]+$/;
    var numberRegexp = /^[0-9]+$/;
    
    export class LettersOnlyValidator implements StringValidator {
        isAcceptable(s: string) {
            return lettersRegexp.test(s);
        }
    }

    export class ZipCodeValidator implements StringValidator {
        isAcceptable(s: string) {
            return s.length === 5 && numberRegexp.test(s);
        }
    }
    }
    // Some samples to try
    var strings = ['Hello', '98052', '101'];
    // Validators to use
    var validators: { [s: string]: Validation.StringValidator; } = {};
    validators['ZIP code'] = new Validation.ZipCodeValidator();
    validators['Letters only'] = new Validation.LettersOnlyValidator();
    // Show whether each string passed each validator
    strings.forEach(s => {
    for (var name in validators) {
    console.log('"' + s + '" ' + (validators[name].isAcceptable(s) ? ' matches ' 
    : ' does not match ') + name);
    }
});

Una vez que se ha definido el módulo, el siguiente paso es usarlo en alguna otra parte del código, es muy parecido a como Node-js funciona y referencia paquetes.

 import validation = require('./Validation');
    var lettersRegexp = /^[A-Za-z]+$/;
    export class LettersOnlyValidator implements validation.StringValidator {
        isAcceptable(s: string) {
        return lettersRegexp.test(s);
    }
}

Genericidad

Otra adición al lenguaje es el Soporte de genericidad en los tipos, que permite que el tipo sea otro parámetro para que así otro parámetro.

 function identity<T>(arg: T): T {
    return arg;
}

De esa manera las llamadas a esa función se puede hacer especificando el tipo o dejando al compilador que infiera el tipo en base al tipo del argumento.

 var output = identity<string>("myString"); // type of output will be 'string'
var output = identity("myString"); // type of output will be 'string'

Herramientas

Visual Studio 2013 update 2 tiene Soporte directamente de TypeScript, con soporte de compilación, depuración e intellisense.

clip_image002

Para empezar con TypeScript está la web de https://www.typescriptlang.org/ de donde se puede encontrar ejemplos, y todo lo necesario para empezar con esta tecnología.

Luis Guerrero.

Technical Evangelist Microsoft Azure.

@guerrerotook