Tipi di dati in Angular

by LFG Scavelli on 23/04/2018

Angular utilizza principalmente "TypeScript", il nuovo linguaggio open source sviluppato da Microsoft che rappresenta un'evoluzione tipizzata di JavaScript basato sulle specifiche ES6 del 2015. Il codice TypeScript viene compilato in semplice codice JavaScript per essere eseguito sulla maggior parte dei browser in uso. Quando si crea un nuovo progetto utilizzando Angular CLI, TypeScript viene automaticamente installato per essere utilizzato da Angular. Nulla ci vieta però di sperimentare un pò di codice eseguendo direttamente il compilatore.

# verifichiamo localmente la versione installata, visibile anche in package.json
$ node_modules/.bin/tsc -v

# compiliamo il file test.ts in test.js
$ node_modules/.bin/tsc -w test.ts

Possiamo comunque procedere con l'installazione di Typescript a livello globale, magari per sperimentare una versione più recente non fornita con Angular.

# installiamo globalmente typescript
npm install -g typescript

# proviamo ad eseguire un po' di codice ts.
tsc test.ts

In TypeScript le variabili possono essere definite in base allo scope (ambito di visibilità) in due differenti modi

// ambito globale, visibile anche al di fuori di un blocco di codice
{ 
    var hostname = '127.0.0.1';
}
console.log(hostname);

// ambito di blocco, visibile solo all'interno del blocco
{ 
    let hostname = '127.0.0.1';
}
console.log(hostname); // Error - hostname non è definita

Possiamo definire inoltre una variabile come costante. Questa dev'essere inizializzata immediatamente

// definiamo una costante con ambito a livello di blocco
const port = 3000;

// consente di mutare le proprietà secondarie degli oggetti
const ports = { ftp: 21 };
ports.ftp = 2121; // Corretto

const too = {};
too['key1'] = 1458;
const demoFreeze = Object.freeze({}); // obblighiamo a non modificare il valore dell'oggetto

TypeScript supporta i seguenti tipi di dati

// contenuto del file app.component.ts
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
import { Component } from '@angular/core';
import { Article } from './article';
import { Person } from './person';

@Component({
  selector: 'app-1',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor () {

    // numerici a virgola mobile
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let num: number;
    let decimal: number;
    let hex: number;
    let binary: number;
    let octal: number;
    num = 123;
    decimal = 1.23;
    hex = 0xf00d;
    binary = 0b1010;
    octal = 0o744;

    // stringa e modelli di stringa
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let title: string = 'App demo';
    let sentence: string;

    // il carattere back-tick consente di scrivere il testo su più righe
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let multiriga = `
      con l'uso del carattere back-tick
      la stringa può
      estendersi su 
      più righe`;
    console.log(multiriga);

    // il seguente modello
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    sentence  = 'Ciao, Il mio nome è ' + title + '.\n\n' +
    'Avrò ' + (num + 1) + ' anni il prossimo mese ';
    
    // equivale al seguente modello - il carattere back-tick consente l'estensione delle variabili
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    sentence  = `Ciao, il mio nome è ${ title }.
    Avrò ${ num + 1 } anni il prossimo mese.`;

    // asserzioni di tipo
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    num = (<string>title).length;
    num = (title as string).length;

    // booleano
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let isView: boolean = false; // true

    // oggetto
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let obj: {name: string, cognome: string, eta: number};
    obj = {'name': 'Vito', 'cognome': 'Marelli', 'eta': 18};
    console.log(obj.eta);

    // array - type[] oppure Array<Type>
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let arrayNum: number[]; // array di numeri
    let arrayNum2: Array<number>; // alternativa a number[]
    let arrayStr: string[]; // array di stringhe - oppure Array<string>;
    arrayNum = arrayNum2 = [1, 2, 3, 4];
    let boolArray: boolean[] = [true, false];

    // array di oggetti
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let arrayObj: Array<Object>;
    arrayObj  = [
      { 'name': 'Vittorio','eta': 36 },
      { 'name': 'Vito','eta': 50 },
      { 'name': 'Alberto','eta': 70 }
    ];
    console.log(arrayObj[1]);
    let arrayObj2: {name: string, cognome:string, eta: number}[];

    // tuple
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    
    let tuple: [string, number];
    tuple = ['hello', 10];
    console.log(tuple[0].substr(1));
    console.log(tuple[1].toString());

    // qualunque tipo
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    
    let qualsiasi: any;
    qualsiasi = 'maybe a string instead';
    qualsiasi = false;
    let list: any[] = [1, true, 'free'];
    list[1] = 100;

    // modelli di object e array - Destructuring
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    
    const {cognome: co, eta: et} = obj;
    const {cognome, eta} = obj; // or var {cognome, eta} = obj;
    console.log(cognome);

    let {w, x, ...altro} = {w: 1, x: 2, y: 3, z: 4};
    console.log(w, x, altro); // 1, 2, {y:3,z:4}

    let [n, m] = arrayNum;
    let [a, b, ...remaining] = arrayNum;
    console.log(a, b, remaining); // 1, 2, [3,4]

    // Nulla e indefinita - possono essere assegnati a qualsiasi altro
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    
    let indefinita: undefined;  // non definita
    let nulla: null = null; // nulla
    let num1: number = null;
    let str: string = undefined;

    // map
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let map = new Map([
      ["A",1]
    ]);

    map.set("B",2)
    .set("C",3)
    .set("D",4);
    console.log(map.get("A")); 
    // map.size; map.has("A"); map.delete("A"); map.clear(); map.keys(); 
    // map.values(); map.entries() ...

    // set - solo chiavi
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let set = new Set(['A']);
    set.add('B')
    .add('C');
    // set.size; set.has("A"); set.delete("B"); set.clear()...

    // tipo function
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let fun: Function;
    fun = () => console.log("Assegno una funzione");

    // enum
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    enum Color {Red=1, Green, Blue}; // con Red=1 l'indice parte da 1 altrimenti da 0
    let c: Color = Color.Green; // Color[2] or 3

    // domain model - class
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let article: Article = new Article('Articolo example', 'bla bla bla');
    let articles: Array<Article>;
    articles = [
      new Article('primo articolo', 'bla bla bla'),
      new Article('secondo articolo', 'bla bla bla'),
      new Article('terzo articolo', 'bla bla bla')
    ];
    let myArticle = articles[1];

    // domain model - interface
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let person: Person;
    person = {
      firstName: 'Vito',
      secondName: 'Marelli',
      eta: 18
    };
    console.log(person.eta);

    // domain model - inline
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let person2: {
      firstName: string;
      secondName: string;
      eta: number;
    };
    person2 = {
      firstName: 'Vito',
      secondName: 'Marelli',
      eta: 18
    };
    type PersonInLine = {
      firstName: string;
      secondName: string;
      eta: number;
    }
    let person3: PersonInLine = {firstName:"Vito",secondName:"Marelli",eta:18};
    let person4: PersonInLine = {firstName:"Marco",secondName:"traitti",eta:18};


    // Tipi letterali - definition
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let hello: 'hello';
    type Direction = "Top" | "Right" | "Bottom" | "Left";
    type OneToFive = 1 | 2 | 3 | 4 | 5;
    type Bools = true | false;

    let d: Direction = "Left";

    // Alias
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    type StrOrNum = string | number;
    let sample: StrOrNum;
    sample = 123;
    sample = '123';
    type Text = string | { text: string };
    type Coordinates = [number, number];
    type Callback = (data: string) => void;

    // controlli sul tipo
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    if (typeof title === 'string') console.log(title.substr(1));
    if (article instanceof Article) console.log(article.toggle);
    if (title in Article) console.log(article.title);

    // Cattura del tipo di variabile
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    let foo = 123;
    let bar: typeof foo = 558;

  }
}

// contenuto del file article.ts
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
export class Article {
    title: string;
    body: string;
    hide: boolean;

    constructor(title: string, body: string) {
        this.title = title;
        this.body = body;
        this.hide = true;
    }

    toggle() {
        this.hide = !this.hide;
    }
}

// contenuto del file person.ts
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
export interface Person {
    firstName: string;
    secondName: string;
    eta: number;
}

Possiamo dichiarare il tipo di una funzione semplicemente impostando il tipo da restituire, con la sintassi : Type e il tipo dei parametri in ingresso.

// : number - restituisce un tipo numerico
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function increment(x: number): number {
  return x + 1;
}

// : string - restituisce un tipo stringa
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function returnString(): string {
  return 'Hello Word';
}

// : boolean - restituisce un tipo boolean
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function foo(x: string | number): boolean {
  if (typeof x === "string") {
    return true;
  } else if (typeof x === "number") {
    return false;
  }
}

// : void - indica che la funzione non restituisce nulla
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function log(message): void {
    console.log(message);
}

// Restituisce un tipo `: Foo` definito nell'interfaccia
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
interface Foo {
    foo: string;
}

function foo(sample: Foo): Foo {
    return sample;
}

// definisce un tipo Generic
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function identity<T>(arg: T): T {
    return arg;
}
let output = identity<string>("myString"); // oppure
let output = identity("myString"); // Il tipo viene riconosciuto aut.mente dal compilatore

// : never - definisce i tipi di valori che non si verificano mai
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function fail(message: string): never { 
    throw new Error(message); 
}

 

Send Comment