Ho fatto una promessa nel precedente post: scriverò quanto ho imparato su Typescript, così da poterlo condividere.
Typescript è un “linguaggio” il cui scopo è introdurre una capacità di tipizzazione in un linguaggio come Javascript notoriamente non tipizzato, quindi “simulando” (di fatto di questo parliamo alla fine) un comportamento basato su aspetti di programmazione orientata agli oggetti, quindi interfacce, classi, enumerazioni, ecc.
In questo post cominceremo ad esplorare questi aspetti, partendo dal vedere come Typescript implementa le classi.
Devo fare una doverosa premessa: non sono mai stato (e probabilmente mai sarò) un “esperto” di scripting lato frontend, quindi alcuni concetti (come appunto classi, interfacce, enumerazioni ecc.) potrebbero già essere stato “introdotti” da altri framework Javascript (eventualmente segnalatemelo) da me sconosciuti o poco usati, e quindi il fatto di averli affrontati in Typescript, rappresenta per me una “novità” vera e propria.
Primo test
Ok, bando alle chiacchiere e andiamo a vedere il codice. Per illustrare i concetti di base, possiamo utilizzare la funzionalità Playground che ci viene messa a disposizione sul sito ufficiale di questo linguaggio, Typescriptlang.org selezionando dalla dropdownlist che troviamo nella zona sinistra la voce “Walkthrough: Classes”, in questo modo ci troveremo nella situazione che vedete di seguito:
In questo post (e probabilmente in altri futui) utilizzeremo il Playground per spiegare i concetti del linguaggio, per poi passare all’utilizzo di Typescript all’interno di Visual Studio.
Come potete vedere nella schermata, il Playground ci mostra contemporaneamente il codice Typescript e il codice Javascript “compilato” (passatemi il termine). In questo modo ci renderemo subito conto della trasformazione a cui viene sottoposto il “nostro” codice per renderlo “comprensibile” a tutti i browser. Infatti il Typescript come linguaggio non è contemplato dagli interpreti dei browser che conoscono molto bene invece Javascript.
Esaminiamo il codice di esempio che vediamo nella schermata:
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return “Hello, ” + this.greeting;
}
}
var greeter = new Greeter(“world”);
var button = document.createElement(‘button’);
button.textContent = “Say Hello”;
button.onclick = function() {
alert(greeter.greet());
}
document.body.appendChild(button);
Come potete vedere, la prima parte è una dichiarazione di una classe, in cui abbiamo un costruttore, un metodo e un attributo. A seguire, una variabile viene istanziata tramite questa classe e quindi utilizzata.
Niente di più simile a quanto potremmo normalmente fare con un linguaggio come C#, tanto per dirne uno.
Eseguendo il codice direttamente dal Playground (tramite il pulsante “Run”) otteniamo il seguente risultato:
Quindi questo ambiente di “test” ci consente anche di fare direttamente delle prove su quanto abbiamo scritto e vederne da subito i risultati. Ovviamente il consiglio naturale è che vanno bene le piccole prove e costrutti limitati che vogliamo in qualche modo verificare, mentre non credo sia utile pensare di usare la Playground per verificare e provare codice di una certa complessità.
Tipizzazione
Un’altra utilità che vediamo in a questo “ambiente” è che possiamo usufruire della funzionalità di Intellisense come se fossimo in un vero e proprio IDE, quindi provando a tipizzare la variabile usata in questo frammento di codice (dopo vedremo in cosa consiste), si ottiene una cosa del genere:
Quello che vedete è il modo tipico con cui si può tipizzare una variabile, ovvero come si definisce in maniera specifica il tipo che dovrà istanziare.
In realtà se non definiamo il tipo che deve ospitare la var, ma ci posizioniamo con il mouse sulla variabile, vediamo che l’ambiente “deduce” comunque il tipo di dato che andrà ad ospitare, quindi il fatto di tipizzarla nella dichiarazione non è necessario, ma sicuramente utile, sia ai fini della lettura del codice, sia per assicurarci di non sbagliare il tipo nella fase di istanziazione vera e propria (magari per un errore di battitura tra classi simili).
Tipi Primitivi di Typescript
Typescript utilizza come tipi primitivi gli stessi già esistenti in Javascript, e con questi il linguaggio si adatta un po’ a tutte le situazioni di allocazione necessarie:
- string, ovviamente corrispondente del tipo stringa (fino a UTF-16)
- number, adibito ad ospitare indifferentemente interi o decimali (fino a 64 bit)
- boolean, equivalente al tipo booleano
Quindi una variabile può essere dichiarata come segue:
var myvariable : string;
e istanziata in questo modo:
myvariable = “test”;
Come in linguaggi più evoluti è possibile fare insieme le due cose:
var myvariable: string = “test”;
Ereditarietà delle classi
Le classi, si sa, possono ereditare le caratteristiche da altre classi, e anche in Typescript ovviamente è possibile farlo, utilizzando la parola extends :
class Vehicle {
name: string;
vehicleType: string;
}
class Car extends Vehicle {
fuelCapacity: number;
color: string;
}
var car: Car = new Car();
car.name = “Aston Martin DBS V12″;
car.vehicleType = “car”;
car.color = “Carbon Black”;
car.fuelCapacity = 80;
L’utilizzo è molto semplice e c’è poco da spiegare, infatti il comportamento è quello previsto quando utilizziamo l’ereditarietà delle classi in linguaggi più evoluti, ovvero che è possibile appunto “ereditare” ed utilizzare tutte le caratteristiche (in questo caso solo proprietà ma anche con funzioni ed altro) dalla classe “padre”.
Enumerazioni
Anche le enumerazioni possono essere definite in Typescript. Se definissimo una enumerazione di tipi di veicolo, potremmo scrivere il codice di prima nel seguente modo:
enum VehicleTypeEnum {
CAR,
BYCICLE,
TRAIN,
AIRPLANE,
TANK
}
class Vehicle {
name: string;
vehicleType: VehicleTypeEnum;
}
class Car extends Vehicle {
fuelCapacity: number;
color: string;
}
var car: Car = new Car();
car.name = “Aston Martin DBS V12”;
car.vehicleType = VehicleTypeEnum.CAR;
car.color = “Carbon Black”;
car.fuelCapacity = 80;
A parte il fatto di comprare un veicolo di tipo TANK (mi era molto utile quando giocavo a GTA ndr), vediamo che il codice in questo modo diventa più definito e più pulito.
Una cosa interessante degli enum è che, come avviene in molti linguaggi tipo C#, ogni valore dell’enum ha un proprio indice numerico equivalente, di default zero-based, ma definibile a piacimento:
Per assegnare un indice diverso lo si assegna semplicemente all’enum:
enum VehicleTypeEnum {
CAR = 150,
BYCICLE = 12,
TRAIN = 1024,
AIRPLANE,
TANK
}
ma attenzione che in questo caso le ultime voci non valorizzate andranno in progressivo con il precedente definito (quindi AIRPLANE sarà 1025 e TANK 1026). Infine sembra che Javascript non faccia molto caso a valori duplicati, quindi attenti a non indicare più voci con lo stesso valore perché potreste non essere avvertiti (almeno sul Playground non ci sono avvisi).
Quindi, con l’esempio precedente possiamo da codice avere in maniera indifferente le due seguenti assegnazioni:
car.vehicleType = 150;
car.vehicleType = VehicleTypeEnum.CAR;
Per la verifica possiamo allo stesso modo fare:
var areEqual = (car.vehicleType == VehicleTypeEnum.CAR);
var areEqual = (car.vehicleType == 150);
Conclusioni
Per questo post è tutto. Abbiamo visto insieme quanto sia facile scrivere una classe, anche se quello di cui abbiamo appena parlato è solo una goccia nell’oceano, ma da qualche parte dovevamo cominciare.
Nei prossimi post aumenteremo questo livello di dettaglio e vedremo altri aspetti del linguaggio Typescript.