Guest post: Typescript: Javascript made easy

Questo post è stato scritto da Andrea Boschin, MVP e presidente di XeDotNet.

Se desiderate approfondire l’argomento nulla di meglio che seguire il Lab che si terrà il prossimo 28 Febbraio a Mestre, durante il meeting organizzato da XeDotNet . In tale occasione si vedrà l’utilizzo di Typescript in una applicazione reale, con la possibilità di provare il codice e vedere con i propri occhi i vantaggi di Typescript.

L’arrivo del nuovo standard HTML5 ha riportato in auge un linguaggio che molti avevano spesso sottovalutato, e magari anche accuratamente evitato. Javascript in effetti è più o meno nato assieme a web stesso, ma per lungo tempo è rimasto confinato a strumento marginale, spesso e volentieri sotto forma di codice generato da controlli server side o magari di semplici trick. La nascita dapprima di strumenti quali JQuery, di tool di sviluppo sempre più raffinati e soprattutto la sempre maggiore trazione dei dispositivi mobili per i quali esso si è infine rivelato unica lingua franca ha portato oggi Javascript ad essere un indiscutibile protagonista con cui, prima o poi, chiunque deve misurarsi.

Purtroppo, chi conosce Javascript, sa che esso è tanto pericoloso quanto bello e raffinato nelle soluzioni che consente. La sua sintassi e semantica in effetti danno smisurate possibilità a chi lo sa usare, ma al tempo stesso rendono le soluzioni difficili da interpretare e manutenere. E’ per questo che Microsoft ha introdotto recentemente Typescript, un nuovo compilatore che è in grado di fornire in output codice Javascript che può essere eseguito in qualunque browser che sia compatibile con ECMASCRIPT 3.0 o 5.0.

Starts with Javascript, Ends with Javascript

A differenza di quanto si può pensare a prima vista, Typescript non richiede alcun plugin nel browser per la semplice ragione che il browser ne eseguirà esclusivamente l’output sotto forma di Javascript, ma noi in fase di sviluppo avremo la possibilità di godere di un linguaggio strongly typed che ci consente una espressività molto più semplice ed efficace.

Ma non basta. In effetti Typescript è un superset di Javascript pertanto, se già si conosce Javascript è immediatamente possibile trarre beneficio dal compilatore Typescript che è è in grado di interpretare qualunque codice Javascript, applicandovi però il controllo dei tipi per inferenza, garantendo immediatamente i vantaggi che un compilatore usualmente garantisce.

Se poi si prende confidenza con i costrutti propri del linguaggio i benefici si moltiplicano. Sarà infatti possibile godere di un linguaggio pienamente ad oggetti, dotato di costrutti evoluti quali i generics. Prendiamo ad esempio il seguente snippet:

    1:  
    2: function move(point, distance, angle)
    3: {
    4:     return {
    5:         x: Math.sin(angle) * distance + point.x,
    6:         y: Math.cos(angle) * distance + point.y
    7:     };
    8: }
    9:  
   10: var point = { x: 0, y: 0 };
   11: var otherPoint = move(point, 100, 45);

Si tratta di codice Javascript a tutti gli effetti ma, se lo digitiamo all’interno dell’editor di Typescript in Visual Studio 2013, avremmo immediatamente il supporto dell’intellisense, in grado di segnalarci che point e otherPoint espongono le proprietà x e y.

E’ chiaro che il compilatore, per quanto faccia un ottimo lavoro non è in grado di comprendere che le proprietà x e y sono le medesime che nei due casi e quindi attribuire loro un tipo “number” come ci si potrebbe aspettare.

Possiamo però dichiarare variabile e valori di ritorno così da poter migliorare la situazione. Typescript in questo caso ammette una sintassi esplicita in cui si descrivono i tipi pur non esistendo delle classi vere e proprie. Ecco un esempio:

    1: function move(
    2:     point: { x: number; y: number },
    3:     distance: number,
    4:     angle: number)
    5:     : { x: number; y: number }
    6: {
    7:     return {
    8:         x: Math.sin(angle) * distance + point.x,
    9:         y: Math.cos(angle) * distance + point.y
   10:     };
   11: }
   12:  
   13: var point: { x: number; y: number } = { x: 0, y: 0 };
   14: var otherPoint = move(point, 100, 45);

Il codice ora non è più Javascript, ma la situazione è nettamente migliorata infatti non sarà più possibile inserire valori errati e l’intellisense stesso ci proporrà le proprietà relative le coordinate. Tuttavia la sintassi è chiaramente ridondante. Possiamo definire una vera e propria classe con il risultato di rendere tutto più leggibile:

    1: class Point 
    2: {
    3:     x: number;
    4:     y: number;
    5: }
    6:  
    7: function move(
    8:     point: Point,
    9:     distance: number,
   10:     angle: number): Point
   11: {
   12:     return {
   13:         x: Math.sin(angle) * distance + point.x,
   14:         y: Math.cos(angle) * distance + point.y
   15:     };
   16: }
   17:  
   18: var point: Point = { x: 0, y: 0 };
   19: var otherPoint = move(point, 100, 45);

Nonostante ci troviamo davanti ad una classe vera e propria, il compilatore riconosce che il valore di ritorno della funzione move è a tutti gli effetti una istanza di Point e, dato che le proprietà sono soddisfatte non emette alcun errore. Trattandosi di un linguaggio ad oggetti vero e proprio, la classe Point può contenere sia proprietà che metodi. In breve, il metodo move può diventare un membro della classe stessa:

    1: class Point 
    2: {
    3:     constructor(public x: number, public y: number)
    4:     { }
    5:  
    6:     public move(distance: number, angle: number): void
    7:     {
    8:         this.x = Math.sin(angle) * distance + this.x;
    9:         this.y = Math.cos(angle) * distance + this.y;
   10:     }
   11: }
   12:  
   13: var point: Point = new Point(100, 100);
   14: point.move(100, 45);

La manipolazione di quello che era un codice Javascript, che pur funzionante lasciava aperta la strada a numerose possibilità di errore, è ora diventato, con pochi e semplici passaggi qualcosa di molto più solido e leggibile che tuttavia sarà compilato in Javascript in grado di essere eseguito in qualunque browser. Ecco qui sotto il risultato:

    1: var Point = (function () {
    2:     function Point(x, y) {
    3:         this.x = x;
    4:         this.y = y;
    5:     }
    6:     Point.prototype.move = function (distance, angle) {
    7:         this.x = Math.sin(angle) * distance + this.x;
    8:         this.y = Math.cos(angle) * distance + this.y;
    9:     };
   10:     return Point;
   11: })();
   12:  
   13: var point = new Point(100, 100);
   14: point.move(100, 45);
Questo e altro, per applicazioni reali

Quello che abbiamo appena visto è solo un piccolo esempio dell’efficacia di questo strumento. La sintassi di Typescript è molto potente e consente l’utilizzo di vari tipi primitivi, generics, array di parametri, e quant’altro.