Il presente articolo è stato tradotto automaticamente.

TypeScript

Informazioni su TypeScript

Peter Vogel

In molti modi, è utile considerare di macchina in modo autonomo. La specifica del linguaggio macchina fa riferimento a TypeScipt come "zucchero sintattico per JavaScript." Che è true e probabilmente un passo essenziale per giungere a un gruppo di destinatari del linguaggio, gli sviluppatori sul lato client JavaScript attualmente in uso.

E, è necessario conoscere JavaScript prima che è possibile comprendere la macchina. In effetti, la specifica del linguaggio (possono essere letti in bit.ly/1xH1m5B) spesso vengono illustrati i costrutti di macchina in termini di codice JavaScript risultante. Ma è altrettanto utile pensare a macchina come un linguaggio di per sé che condivide le funzioni JavaScript.

Ad esempio, come C#, macchina è un linguaggio di tipi di dati, che offre un supporto di IntelliSense e controllo, tra l'altro in fase di compilazione. Come C#, macchina include espressioni lambda e generica (o equivalente).

Ma la macchina, naturalmente, non è C#. Comprendere le funzionalità univoche sulla macchina è importante quanto comprendere cosa macchina condivide con linguaggio lato server che si sta utilizzando. Il sistema del tipo di macchina è diverso (e più semplice) di C#. Macchina sfrutta la conoscenza di altri modelli a oggetti in modo univoco e viene eseguito in modo diverso rispetto a C# di ereditarietà. E poiché la macchina viene compilato in JavaScript, macchina condivide molti dei relativi elementi di base con JavaScript, a differenza di C#.

La domanda quindi rimane, "si scrive client -­codice sul lato in questa lingua o in JavaScript?"

Macchina è dati tipizzati

Macchina non dispone di molti tipi di dati incorporati, è possibile utilizzare per dichiarare le variabili, ovvero solo stringa, numero e un valore booleano. Questi tre tipi sono un sottotipo di qualsiasi tipo (che è anche possibile utilizzare nella dichiarazione di variabili). È possibile impostare o verificare le variabili dichiarate con i quattro tipi con i tipi di null o undefined. È inoltre possibile dichiarare metodi come void, che indica che non restituiscono alcun valore.

In questo esempio si dichiara una variabile come stringa:

var name: string;

È possibile estendere questo sistema di tipo semplice con i valori enumerati e quattro tipi di oggetto: interfacce, classi, matrici e funzioni. Il codice seguente, ad esempio, definisce un'interfaccia (un tipo di oggetto) con il nome ICustomerShort. L'interfaccia include due membri: una proprietà denominata Id e un metodo denominato CalculateDiscount:

interface ICustomerShort
{
  Id: number;
  CalculateDiscount(): number;
}

Come in C#, è possibile utilizzare le interfacce nella dichiarazione di variabili e tipi restituiti. Questo esempio dichiara il variabile cs come tipo di ICustomerShort:

var cs: ICustomerShort;

È inoltre possibile definire tipi di oggetto come classi, che, a differenza delle interfacce, possono contenere codice eseguibile. In questo esempio viene definita una classe denominata CustomerShort con una proprietà e un metodo:

class CustomerShort
{
  FullName: string;
  UpdateStatus( status: string ): string
  {
    ...manipulate status... 
    return status;
  }
}

Come le versioni più recenti di C#, non è necessario fornire il codice di implementazione quando si definisce una proprietà. La dichiarazione del nome e del tipo semplice è sufficiente. Le classi possono implementare una o più interfacce, come illustrato nella Figura 1, che aggiunge l'interfaccia ICustomerShort, con la proprietà per la classe CustomerShort.

Figura 1 aggiungere un'interfaccia a una classe

class CustomerShort implements ICustomerShort
{
  Id: number;
  FullName: string;
  UpdateStatus(status: string): string
  {
    ...manipulate status...
    return status;
  }
  CalculateDiscount(): number
  {
    var discAmount: number;
    ...calculate discAmount...
    return discAmount;
  }
}

Come Figura 1 illustra la sintassi per l'implementazione di un'interfaccia è semplice macchina come in C#. Per implementare i membri dell'interfaccia è sufficiente aggiungere i membri con lo stesso nome anziché il nome dell'interfaccia ai membri della rispettiva classe. In questo esempio semplicemente aggiunto Id e CalculateDiscount alla classe per implementare ICustomerShort. Macchina è inoltre possibile utilizzare valori letterali di tipo oggetto. Questo codice imposta la variabile cst a un oggetto letterale contenente una proprietà e un metodo:

var csl = {
            Age: 61,
            HaveBirthday(): number
          {
            return this.Age++;
          }
        };

Questo esempio viene utilizzato un tipo di oggetto per specificare il valore restituito del metodo UpdateStatus:

UpdateStatus( status: string ): { 
  status: string; valid: boolean }
{
  return {status: "New",
          valid: true
         };
}

Oltre ai tipi di oggetto (classe, interfaccia, letterale e matrice), è inoltre possibile definire tipi di funzione che descrivono la firma di una funzione. Il codice seguente riscrive CalculateDiscount dalla mia classe CustomerShort per accettare un singolo parametro chiamato discountAmount:

interface ICustomerShort
{
  Id: number;
  CalculateDiscount( discountAmount:
    ( discountClass: string, 
      multipleDiscount: boolean ) => number): number
}

Tale parametro viene definito utilizzando un tipo di funzione che accetta due parametri (uno di stringa, uno dei valore booleano) e restituisce un numero. Se siete uno sviluppatore C#, si noterà che la sintassi è molto simile a un'espressione lambda.

Una classe che implementa questa interfaccia sarebbe analogo Figura 2.

Figura 2 di questa classe implementa l'interfaccia corretta

class CustomerShort implements ICustomerShort
{
  Id: number;
  FullName: string;
  CalculateDiscount( discountedAmount:
    ( discountClass: string, 
      multipleDiscounts: boolean ) => number ): number
  {
    var discAmount: number;
    ...calculate discAmount...
    return discAmount;
  }
}

Come le versioni recenti di C#, macchina deduce anche il tipo di dati di una variabile dal valore a cui viene inizializzata la variabile. In questo esempio, macchina presupporrà che la variabile myCust è di CustomerShort:

var myCust= new CustomerShort();
myCust.FullName = "Peter Vogel";

Ad esempio C#, è possibile dichiarare variabili utilizzando un'interfaccia e quindi impostare la variabile a un oggetto che implementa tale interfaccia:

var cs: ICustomerShort;
cs = new CustomerShort();
cs.Id = 11;
cs.FullName = "Peter Vogel";

Infine, è anche possibile utilizzare parametri di tipo (che assomigliano in modo insolito generics in C#) per consentire il codice chiamante di specificare il tipo di dati da utilizzare. In questo esempio è il codice che crea il set di classe, il tipo di dati della proprietà Id:

class CustomerTyped<T>
{
  Id: T;
}

Questo codice imposta il tipo di dati della proprietà Id su una stringa prima di utilizzarlo:

var cst: CustomerTyped<string>;
cst = new CustomerTyped<string>();
cst.Id = "A123";

Per isolare le classi, interfacce e altri membri pubblici ed evitare conflitti di nomi, è possibile dichiarare questi costrutti all'interno di moduli molto simile a spazi dei nomi in C#. È possibile contrassegnare gli elementi che si desidera rendere disponibile ad altri moduli con la parola chiave di esportazione. Il modulo in nella figura 3 Esporta due interfacce e una classe.

Figura 3 esportazione due interfacce e una classe

module TypeScriptSample
{
  export interface ICustomerDTO
  {
    Id: number;
  }
  export interface ICustomerShort extends ICustomerDTO
  {
    FullName: string;
  }
  export class CustomerShort implements ICustomerShort
  {
    Id: number;
    FullName: string;
  }

Per utilizzare i componenti esportati, è possibile far precedere il nome del componente con il nome del modulo come nel seguente esempio:

var cs: TypeScriptSample.CustomerShort;

Oppure è possibile utilizzare la parola chiave Importa macchina per stabilire un collegamento al modulo:

import tss = TypeScriptSample;
...
var cs:tss.CustomerShort;

Macchina è flessibile sull'inserimento dei dati

Tutto ciò dovrebbe risultare familiare se siete un programmatore C#, ad eccezione forse lo storno di dichiarazioni di variabili (variabile primo il nome, tipo di dati in secondo luogo) e valori letterali di oggetto. Tuttavia, praticamente tutti i dati digitando macchina è facoltativo. La specifica descrive i tipi di dati come "annotazioni". Se si omettono i tipi di dati (e macchina non dedurre il tipo di dati), tipi di dati predefinito per qualsiasi tipo.

Macchina non richiede il tipo di dati rigoroso corrispondenza. Macchina utilizza ciò che la specifica definisce "definizione di sottotipo strutturali" per determinare la compatibilità. Questo è simile a quello che viene spesso definito "duck typing". A macchina, due classi sono considerate identiche se hanno membri con gli stessi tipi. Ad esempio, ecco un cliente­breve classe che implementa un'interfaccia denominata ICustomerShort:

interface ICustomerShort
{
  Id: number;
  FullName: string;
}
class CustomerShort implements ICustomerShort
{
  Id: number;
  FullName: string;
}

Ecco una classe denominata CustomerDeviant che è simile alla mia classe CustomerShort:

class CustomerDeviant
{
  Id: number;
  FullName: string;
}

Grazie alla definizione di sottotipo strutturali, è possibile utilizzare CustomerDevient con le variabili definite con la classe CustomerShort o ICustomerShort interfaccia. Questi esempi viene utilizzata in modo intercambiabile CustomerDeviant con le variabili dichiarate come CustomerShort o ICustomerShort:

var cs: CustomerShort;
cs = new CustomerDeviant
cs.Id = 11;
var csi: ICustomerShort;
csi = new CustomerDeviant
csi.FullName = "Peter Vogel";

Questa flessibilità, è possibile assegnare i valori letterali oggetto macchina alle variabili dichiarate come classi o interfacce, purché siano strutturalmente compatibile, come qui sono:

var cs: CustomerShort;
cs = {Id: 2,
      FullName: "Peter Vogel"
     }
var csi: ICustomerShort;
csi = {Id: 2,
       FullName: "Peter Vogel"
      }

Questo lead in funzionalità specifiche della macchina intorno a tipi, i supertipi e sottotipi porta al problema generale di assegnabilità, saltate qui. Tali funzionalità consentirebbe CustomerDeviant, ad esempio, di avere membri che non sono presenti in CustomerShort senza provocare il mio codice di esempio avere esito negativo.

Macchina è la classe

La specifica di macchina fa riferimento al linguaggio come implementazione "la classe pattern [con] catene di prototipi di implementare molte variazioni su meccanismi di ereditarietà object-oriented." In pratica, significa che macchina non è solo tipi di dati, ma orientata in modo efficace.

Nello stesso modo che un'interfaccia C# può ereditare da un'interfaccia di base, un'interfaccia macchina può estendere un'altra interfaccia, anche se quell'interfaccia è definita in un modulo diverso. Questo esempio estende l'interfaccia ICustomerShort per creare una nuova interfaccia denominata ICustomerLong:

interface ICustomerShort
{
  Id: number;
}
interface ICustomerLong extends ICustomerShort
{
  FullName: string;
}

L'interfaccia ICustomerLong avrà due membri: FullName e ID. Nell'interfaccia unito, i membri di interfaccia visualizzato per primo. Pertanto, l'interfaccia ICustomerLong è equivalente a questa interfaccia:

interface ICustomerLongPseudo
{
  FullName: string;
  Id: number;
}

Una classe che implementa ICustomerLong necessario entrambe le proprietà:

class CustomerLong implements ICustomerLong
{
  Id: number;
  FullName: string;
}

Le classi possono estendere altre classi nello stesso modo in cui un'interfaccia può estendere un altro. La classe in nella figura 4 estende CustomerShort e aggiunge una nuova proprietà alla definizione. Esplicita getter e setter viene utilizzato per definire le proprietà (anche se non in modo particolarmente utile).

Figura 4 proprietà definita con funzioni getter e setter

class CustomerShort
{
  Id: number;
}
class CustomerLong extends CustomerLong
{
  private id: number;
  private fullName: string;
  get Id(): number
  {
    return this.id
  }
  set Id( value: number )
  {
    this.id = value;
  }
  get FullName(): string
  {
    return this.fullName;
  }
  set FullName( value: string )
  {
    this.fullName = value;
  }
}

Macchina applica la procedura consigliata per l'accesso ai campi interni (ad esempio id e fullName) tramite un riferimento alla classe (this). Le classi possono essere funzioni costruttore che includono una funzione in che C# è sufficiente ha adottato: definizione automatica dei campi. La funzione di costruzione in una classe di macchina deve essere denominata costruttore e sono definite come proprietà e inizializzate dai valori passati ad essi automaticamente i parametri pubblici. In questo esempio, il costruttore accetta un singolo parametro denominato società di tipo stringa:

export class CustomerShort implements ICustomerShort
{
  constructor(public Company: string)
  {       }

Poiché il parametro della società è definito come pubblica, la classe ottiene anche una proprietà pubblica denominata società inizializzato dal valore passato al costruttore. Grazie a tale funzionalità, la composizione variabile verrà impostata su "PH & VIS," come nell'esempio seguente:

var css: CustomerShort;
css = new CustomerShort( "PH&VIS" );
var comp = css.Company;

Dichiarazione di parametro di un costruttore privato crea una proprietà interna è solo possibile accedere dal codice all'interno dei membri della classe tramite la parola chiave in questo. Se il parametro non è dichiarato come pubblico o privato, non viene generata alcuna proprietà.

La classe deve avere un costruttore. Come in C#, se non si fornisce uno, verrà utilizzato uno automaticamente. Se la classe estende un'altra classe, qualsiasi costruttore che si crea deve includere una chiamata a super. Si chiama il costruttore della classe che estende. In questo esempio include un costruttore con una chiamata a super che fornisce parametri al costruttore della classe base:

class MyBaseClass
{
  constructor(public x: number, public y: number ) { }   
}
class MyDerivedClass extends MyBaseClass
{
  constructor()
  {
    super(2,1);
  }
}

Macchina eredita in modo diverso

Anche in questo caso tutti sembrerà familiare se siete un programmatore C#, ad eccezione di alcune parole chiave divertenti (estensione). Ma anche in questo caso si estende una classe o un'interfaccia non è molto diversa dai meccanismi di ereditarietà in C#. La specifica di macchina vengono utilizzati i termini usuali per la classe che viene estesa ("classe base") e la classe che estende ("classe derivata"). Tuttavia, la specifica fa riferimento a una classe "patrimonio specification", ad esempio, anziché utilizzare la parola "ereditarietà".

Per cominciare, macchina contiene meno opzioni rispetto a C#, per quanto riguarda la definizione di classi base. È possibile dichiarare la classe o membri non ignorabile, astratta o virtuale (anche se le interfacce forniscono molte funzionalità che fornisce una classe base virtuale).

Non esiste alcun modo per impedire che alcuni membri non ereditati. Una classe derivata eredita tutti i membri della classe base, tra cui il pubblico e i membri privati (tutti i membri pubblici della classe base sono sottoponibile a override membri privati non sono). Per eseguire l'override di un membro pubblico, è sufficiente definire un membro della classe derivata con la stessa firma. Sebbene sia possibile utilizzare la parola chiave super per accedere a un metodo pubblico da una classe derivata, è possibile accedere una proprietà nella classe base utilizzando super (anche se è possibile eseguire l'override della proprietà).

Macchina consente di estendere un'interfaccia semplicemente dichiarando un'interfaccia con un nome identico e nuovi membri. Consente di estendere il codice JavaScript esistente senza creare un nuovo tipo denominato. Nell'esempio riportato in Figura 5 definisce l'interfaccia ICustomerMerge tramite due definizioni di interfaccia separata e quindi implementa l'interfaccia in una classe.

Figura 5 l'interfaccia ICustomerMerge definita tramite due definizioni di interfaccia

interface ICustomerMerge
{
  MiddleName: string;
}
interface ICustomerMerge
{
  Id: number;
}
class CustomerMerge implements ICustomerMerge
{
  Id: number;
  MiddleName: string;
}

Le classi possono anche estendere altre classi, ma non le interfacce. A macchina, le interfacce possono inoltre estendere le classi, ma solo in modo che prevede ereditarietà. Quando un'interfaccia estende una classe, l'interfaccia include tutti i membri di classe (pubblici e privati), ma senza le implementazioni della classe. In nella figura 6, l'interfaccia ICustomer avrà l'id membro privato, un membro pubblico Id e il membro pubblico MiddleName.

Figura 6, una classe estesa con tutti i membri

class Customer
{
  private id: number;
  get Id(): number
  {
    return this.id
  }
  set Id( value: number )
  {
    this.id = value;
  }
}
interface ICustomer extends Customer
{
  MiddleName: string;
}

L'interfaccia ICustomer dispone di una significativa restrizione, è possibile utilizzarlo solo con le classi che estendono la classe stessa interfaccia estesa (in questo caso, che è la classe Customer). Macchina è necessario includere i membri privati dell'interfaccia da cui ereditare la classe che estende l'interfaccia, invece di essere reimplementato nella classe derivata. Una nuova classe che utilizza l'interfaccia ICustomer necessario, ad esempio, per fornire un'implementazione per MiddleName (perché viene specificato solo nell'interfaccia). Lo sviluppatore che utilizza ICustomer possibile scegliere di ereditare oppure eseguire l'override di metodi pubblici della classe cliente, ma non sarà possibile eseguire l'override del membro id privato.

In questo esempio viene illustrata una classe, denominata NewCustomer, che implementa l'interfaccia ICustomer ed estende la classe Customer come richiesto. In questo esempio NewCustomer eredita l'implementazione dell'Id del cliente e fornisce un'implementazione per MiddleName:

class NewCustomer extends Customer implements ICustomer
{
  MiddleName: string;
}

Questa combinazione di interfacce, classi, implementazione ed exten­alle norme sion fornisce un modo controllato per definire per estendere le classi definite in altri modelli a oggetti di classi (per ulteriori dettagli, consulta sezione 7.3 della specifica di linguaggio "Classi di estensione di interfacce"). Insieme con la capacità della macchina di utilizzare le informazioni sulle altre librerie JavaScript, è possibile scrivere codice macchina che funziona con gli oggetti definiti in tali librerie.

Macchina è a conoscenza di librerie

Oltre a conoscere le classi e le interfacce definite nell'applicazione, è possibile fornire la macchina con informazioni su altre librerie di oggetti. Che viene gestita tramite la macchina dichiarare la parola chiave. Questo crea le chiamate di specifica "dichiarazione ambientale". Molti senza dover utilizzare la parola chiave declare direttamente poiché è possibile trovare il file di definizione per la maggior parte delle librerie JavaScript sul sito DefinitelyTyped in definitelytyped.org. Questi file di definizione, macchina può effettivamente "leggere la documentazione" sulle librerie a cui si desidera lavorare.

Ovviamente, "Leggere la documentazione" si intende ottenere dati -­digitato supporto IntelliSense e il controllo quando si utilizzano gli oggetti che compongono la libreria in fase di compilazione. Inoltre consente a macchina, in determinate circostanze, di dedurre il tipo di una variabile dal contesto in cui viene utilizzato. Grazie al file di definizione del lib.d.ts incluso in macchina, macchina presuppone che l'ancoraggio variabile è di tipo HTMLAnchorElement nel codice riportato di seguito:

var anchor = document.createElement( "a" );

Il file di definizione specifica che è il risultato restituito dal metodo createElement quando il metodo viene passato la stringa "a". Ancoraggio è un HTMLAnchorElement sapere significa macchina sa che la variabile di ancoraggio supporta, ad esempio, il addEvent­metodo Listener.

I dati della macchina l'inferenza del tipo anche works con tipi di parametro. Ad esempio, il metodo addEventListener accetta due parametri. Il secondo è una funzione che passano addEventListener un oggetto di tipo PointerEvent. Macchina sa che e supporta l'accesso alla proprietà cancelBubble della classe PointerEvent all'interno della funzione:

span.addEventListener("pointerenter", function ( e )
{
  e.cancelBubble = true;
}

Allo stesso modo tale lib.d.ts fornisce informazioni sul modello DOM HTML, i file di definizione per altri JavaScript forniscono una funzionalità simile. Dopo aver aggiunto il file backbone.d.ts al progetto, ad esempio, è possibile dichiarare una classe che estende la classe modello Backbone e mia interfaccia utilizzando il codice:

class CustomerShort extends bb.Model implements ICustomerShort
{
}

Se siete interessati a informazioni dettagliate su come utilizzare la macchina con Backbone e foratura, consultare i miei articoli di macchina pratico in bit.ly/1BRh8NJ. Nel nuovo anno, io parlerò in dettaglio l'utilizzo di macchina con angolare.

Non esiste più per macchina di riportato di seguito. Versione macchina 1.3 è previsto per includere tipi di dati unione (per il supporto, ad esempio, le funzioni che restituiscono un elenco di tipi specifici) e Tuple. Il team di macchina collabora con altri team di applicazione dei dati in testo digitato in JavaScript (flusso e angolare) per garantire la che macchina funzionerà con più ampia librerie un intervallo di JavaScript possibile.

Se è necessario eseguire un'operazione che supporta JavaScript e macchina non consentiva di eseguire, è sempre possibile integrare il codice JavaScript perché la macchina è un superset di JavaScript. Quindi la domanda rimane, quale di questi linguaggi è preferibile utilizzare per scrivere il codice lato client?


Peter Vogel tratta di un'entità con PH & V Information Services, specializzato in sviluppo di applicazioni Web con esperienza in SOA, sviluppo lato client e la progettazione dell'interfaccia utente. PH & client V includono la banca imperiale canadese del commercio, Volvo e Microsoft. Egli inoltre insegna e scrive corsi per Learning Tree International e la colonna .NET pratici per VisualStudioMagazine.com.

Grazie al seguente esperto tecnico di Microsoft per la revisione di questo articolo: Ryan Cavanaugh