back to top

I tipi di dato disponibili in TypeScript

Come detto nella precedente lezione, TypeScript estende il linguaggio Javascript aggiungendo alcune interessanti funzionalità. Fra queste vi è il controllo statico sui tipi di dato già in fase di compilazione. TypeScript fornisce alcuni strumenti utili come il sistema delle annotazioni di tipo che consente di specificare in maniera esplicita il tipo di una certa variabile. Tale sistema è però opzionale. Ciò permette di inserire del normale codice Javascript all’interno di un file .ts senza ricevere nessun messaggio di errore da parte del transpiler.

I tipi di dato in Javascript

Javascript è un linguaggio a tipizzazione dinamica in cui esistono sette tipi di dati, sei dei quali sono dei tipi di dato primitivo immutabile.

I tipi di dato primitivo sono:

  • Boolean
  • Number
  • Null
  • String
  • Symbol
  • Undefined

A questi bisogna aggiungere il tipo di dato Object.

Annotazioni dei tipi in TypeScript

TypeScript prevede un sistema opzionale di annotazioni dei tipi che consente di specificare in modo esplicito qual è il tipo di una variabile, di una costante o la segnatura di una funzione.

const esempioCostante: string = 'ciao';
let variabile: number = 73;
let altraVariabile: string;

La sintassi da usare per costanti o variabili consiste nell’inserire il carattere ‘: ‘ tra il nome e il tipo della variabile.

function foo(a: string, b: number): number {...}
function bar(a: number, b: number=1): boolean {...}
function baz(a: boolean, b = true): boolean {...}

Per quanto riguarda la segnatura delle funzioni, possiamo specificare il tipo dei parametri ed usare eventualmente un valore di default. In quest’ultimo caso possiamo anche omettere il tipo per questioni di leggibilità del codice. TypeScript dedurrà automaticamente il tipo del parametro a partire dal valore di default.

I tipi di dato in TypeScript

TypeScript supporta tutti i tipi visti sopra in aggiunta ad alcuni non disponibili in Javascript.

Il tipo string

Come Javascript, TypeScript supporta il tipo string per variabili di tipo testuale che possono essere racchiuse fra virgolette singole (‘) o doppie(").

const car: string = "Lamborghini Countach";
let car2: string = 'Aston Martin DB5';
car2 = 'Shelby GT500 Eleanor';
car2 = 1967; // Errore: Type '1967' is not assignable to type 'string'

TypeScript supporta, come ES2015, le stringhe template che sono racchiuse dal carattere backtick (`) e possono contenere al loro interno delle espressioni attraverso il simbolo $ seguito da parentesi graffe (${}).

const ferrari: string = '250 gto';
const inizioProduzione: number = 1962;
const fineProduzione: number = 1964;

let template: string = `La ${ferrari.toUpperCase()} è stata prodotta 
dalla Ferrari fra il ${inizioProduzione} e il ${fineProduzione}`;

Il tipo number

Come in Javascript esiste il tipo number che può essere usato per le variabili numeriche in formato decimale, binario, esadecimale e ottale.

const numeroDecimale: number = 73;
const numeroBinario:number = 0b1001001;
const numeroEsadecimale: number = 0x49;
const numeroOttale: number = 0o111;

Il tipo boolean

Per dichiarare una variabile booleana, che può assumere come unici valori true o false, basta usare la keyword boolean.

let foo: boolean = false;

Gli Array in TypeScript

Per dichiarare una variabile di tipo array, sono disponibili due diverse sintassi equivalenti. La prima prevede l’uso del tipo degli elementi seguito da parentesi quadre come mostrato nell’esempio che segue.

const videoGameConsoles: string[] = ['PS4', 'Xbox One S', 'Switch'];

La seconda consiste nell’usare il tipo generico Array<tipoElementi> in cui viene specificato il tipo degli elementi fra parentesi angolari.

const consoles2018: Array<string> = ['PS4', 'Xbox One S', 'Switch'];

Il tipo Tuple

Le Tuple costituiscono un nuovo tipo di dato introdotto in TypeScript e non presente in Javascript. Possono essere usate per rappresentare un array di dimensione fissa i cui elementi sono di tipo diverso.

let driver: [string, number] = ['Ayrton Senna', 3];

Nell’esempio mostrato abbiamo una variabile di tipo Tuple in cui memorizziamo come primo elemento il nome ‘Ayrton Senna’ e come secondo elemento il numero di mondiali vinti.

Le enumerazioni in TypeScript

Le enumerazioni costituiscono un altro tipo di dato non presente in Javascript. Per definire le enumerazioni si usa la parola riservata enum seguita dal nome della particolare enumerazione. Fra parentesi graffe vengono poi elencati dei possibili elementi che consentono di identificare dei valori numerici in maniera più semplice e facilmente ricordabile.

enum PuntoCardinale {Nord, Sud, Ovest, Est};
const nord: PuntoCardinale = PuntoCardinale.Nord; // 0

Se inseriamo il codice riportato sopra in un file .ts e lanciamo il comando tsc, viene generato un file .js come il seguente:

var PuntoCardinale;
(function (PuntoCardinale) {
    PuntoCardinale[PuntoCardinale["Nord"] = 0] = "Nord";
    PuntoCardinale[PuntoCardinale["Sud"] = 1] = "Sud";
    PuntoCardinale[PuntoCardinale["Ovest"] = 2] = "Ovest";
    PuntoCardinale[PuntoCardinale["Est"] = 3] = "Est";
})(PuntoCardinale || (PuntoCardinale = {}));
;
var nord = PuntoCardinale.Nord; // 0

In questo caso PuntoCardinale è un oggetto come quello mostrato sotto:

// il tipo enum PuntoCardinale viene trasformato nel seguente oggetto Javascript
{ 
  '0': 'Nord',
  '1': 'Sud',
  '2': 'Ovest',
  '3': 'Est',
  Nord: 0,
  Sud: 1,
  Ovest: 2,
  Est: 3 
}

Ad ogni elemento dell’enumerazione è associato un numero progressivo a partire da 0 che consente di accedere all’elemento. È comunque possibile assegnare a ciascun elemento dei valori personalizzati o indicare il primo numero della sequenza da assegnare agli elementi dell’enumerazione.

enum PuntoCardinale {Nord = 100, Sud, Ovest, Est};
const nord: PuntoCardinale = PuntoCardinale.Nord; // 100
const sud: PuntoCardinale = PuntoCardinale.Sud; // 101
const ovest: PuntoCardinale = PuntoCardinale.Ovest // 102
const est: PuntoCardinale = PuntoCardinale.Est // 103
enum PuntoCardinale {Nord = 12, Sud = 6, Ovest = 9, Est = 3};
const nord: PuntoCardinale = PuntoCardinale.Nord; // 12
const sud: PuntoCardinale = PuntoCardinale.Sud; // 6
const ovest: PuntoCardinale = PuntoCardinale.Ovest // 9
const est: PuntoCardinale = PuntoCardinale.Est // 3

I tipi Unione

Grazie al carattere ‘|’ è possibile combinare più tipi diversi in un nuovo ‘tipo composto’. Se, per esempio, consideriamo il frammento di codice riportato sotto, la variabile prezzo può essere di tipo string oppure di tipo number.

let prezzo: string | number;

prezzo = 10.01;
prezzo = '€2.49';

È anche possibile definire un alias e creare un nuovo nome per il tipo Unione come mostrato nel frammento di codice che segue.

// crea un nuovo nome per il tipo 'string | number'
type Price = string | number;

let prezzo: Price;

prezzo = 10.01;
prezzo = '€2.49';

I tipi Null e Undefined

Anche in TypeScript esistono due tipi distinti per undefined e null che di default sono sottotipi di tutti gli altri tipi presenti in TypeScript. Ciò comporta che è possibile assegnare il valore null o undefined a qualsiasi variabile. Il flag –strictNullChecks, passato come argomento al comando tsc o inserito nel file di configurazione tsconfig.json, consente di cambiare il comportamento appena descritto. In ques’ultimo caso null e undefined possono essere assegnati solo ai rispettivi tipi.

// Type 'undefined' is not assignable to type 'null'.
let pizza: null = undefined; // ERROR
// Type 'null' is not assignable to type 'undefined'.
let pizza2: undefined = null; // ERROR

let pizza3: null = null; // OK
let pizza4: undefined = undefined; // OK

Se usiamo il flag –strictNullChecks e vogliamo assegnare null a una variabile di altro tipo possiamo usare il tipo Union come mostrato sotto.

let pizza5: string | null = null;

Il tipo void

Il tipo void viene solitamente usato come tipo del valore di ritorno nelle funzioni che non restituiscono un valore definito.

function log(message: string): void {
  console.log(message);
}

Il tipo never

Il tipo never è stato creato sostanzialmente per essere usato come valore di ritorno di funzioni che non restituiscono mai un valore come nel caso di funzioni in cui viene eseguito un ciclo infinito. (La funzione non viene mai portata a termine) Un altro esempio in cui viene usato il tipo never è costituito dalle funzioni che lanciano sempre un’eccezione per cui non completano mai la loro esecuzione.

function lanciaErrore(messaggio: string): never {
    throw new Error(messaggio);
}

function loopInfinito(): never {
  while (true) {}
}

Il tipo any in TypeScript

L’ultimo tipo che vediamo è any che può essere usato quando non si conosce a priori il tipo di una variabile. A una variabile di tipo any è possibile assegnare qualsiasi tipo di valore. Inoltre su tali variabili non viene effettuato alcun controllo a tempo di compilazione. Un altro impiego del tipo any è per array contenenti elementi di diverso tipo.

const arr: any[] = ['ciao', [1, 2, 3], 17];
let foo: any = 'foo';
foo = 13;
foo = {a: 1, b: 2};

Se non si specifica il tipo di una variabile, TypeScript cercherà di dedurlo da solo. Nel caso non ci dovesse riuscire, a una variabile o a un parametro viene assegnato il tipo any. Se prendiamo in considerazione la funzione riportata in basso, TypeScript non può concludere nulla sul tipo del parametro messaggio che per questo sarà di tipo any.

// messaggio: any
function log(messaggio): void { 
  console.log(messaggio);
}

Ci sono alcuni casi in cui si vuole evitare questo tipo di comportamento. Grazie all’opzione –noImplicitAny (oppure settando noImplicitAny: true in un file tsconfig.json), se il compilatore non riesce a inferire il tipo di un parametro, viene riportato un errore come quello mostrato in basso. Bisogna evidenziare che, lanciando il comando tsc, verrà comunque generato un file .js a partire dal file .ts in cui è presente l’errore.

// Parameter 'messaggio' implicitly has an 'any' type
function log(messaggio): void { // ERROR
  console.log(messaggio);
}

Asserzione di tipo

Abbiamo visto che TypeScript fa il possibile per inferire il tipo di una variabile o di un parametro se non specificato esplicitamente. Attraverso il meccanismo delle asserzioni di tipo possiamo comunicare al compilatore di avere maggiori informazioni e dettagli su un certo parametro e sovrascrivere il tipo dedotto dal compilatore. Il meccanismo delle asserzioni di tipo non ha nessun effetto sull’esecuzione a runtime, serve solo per evidenziare in fase di compilazione che un certo parametro o variabile deve avere come tipo quello indicato. È possibile usare due diverse sintassi equivalenti:

  • Racchiudere il tipo dentro delle parentesi angolari
  • Usare la keyword as
// Alternativa 1: asserzione di tipo con parentesi angolari

function baz(message: any): void {
  // message: any
  const msg = (<string>message); // msg: string 
  msg.toUpperCase();
}
// Alternativa 2: asserzione di tipo con keyword as

function baz(message: any): void {
  // message: any
  const msg = (message as string); // msg: string 
  msg.toUpperCase();
}

L’operatore di asserzione di tipo non nullo !

Concludiamo questa lezione parlando brevemente dell’operatore di asserzione di tipo non nullo (!) che si pospone al nome di una variabile per indicare che quest’ultima non è null o undefined in contesti in cui il compilatore non è in grado di dedurlo. In sostanza l’operatore ! elimina i tipi null e undefined dalla lista dei possibili tipi di una variabile.

let nome: string | null;

function assegnaNome(nuovoNome: string): void {
  nome = nuovoNome;
}

assegnaNome('Lisa');

/* SENZA USO DELL'OPERATORE DI ASSERZIONE DI TIPO NON NULLO
  Variable 'nome' is used before being assigned.
  Object is possibly 'null'.
*/
console.log(nome.length); // ERRORE in fase di compilazione
let nome: string | null;

function assegnaNome(nuovoNome: string): void {
  nome = nuovoNome;
}

assegnaNome('Lisa');

// Versione Corretta
// NOTATE il punto esclamativo 'nome!' 
console.log(nome!.length); // 4

Conclusioni

In questa lezione abbiamo presentato quelli che sono i tipi di dato disponibili in TypeScript e abbiamo visto come poter utilizzare il sistema opzionale delle annotazioni per specificare in maniera esplicita il tipo di una variabile, di una costante o la segnatura di una funzione.

Pubblicitร 
Articolo precedente
Articolo successivo