2013-01-15 12 views
70

In TypeScript, quando si creano i file di dichiarazione di origine .d.ts, che è preferibile e perché?Qual è la differenza tra "declare classe" e "interfaccia" in TypeScript

declare class Example { 
    public Method(): void; 
} 

o

interface Example { 
    Method(): void; 
} 

Le differenze che posso dire sono che le interfacce non possono avere metodi statici, quindi è necessario utilizzare una classe per questo. Entrambi non producono alcun output JS, quindi forse non importa?

+0

Vedere http://stackoverflow.com/a/14323673/1704166 –

+0

Non penso che nessuno di questi aiuti possa descrivere che usereste uno su un altro poiché entrambi possono ottenere la stessa cosa senza output JS. – Chris

risposta

118

interface è per quando si desidera semplicemente descrivere la forma di un oggetto. Non esiste la generazione di codice, mai, per le interfacce: sono solo un artefatto nel sistema dei tipi. Non vedrai alcuna differenza nella generazione del codice per una classe a seconda che abbia o meno una clausola implements.

declare class è per quando si vuole descrivere un esistente classe (di solito una classe dattiloscritto, ma non sempre) che sta per essere esternamente presente (ad esempio, si dispone di due file .ts che compilano a due .js i file e entrambi sono inclusi tramite i tag script in una pagina Web). Se si eredita da extends utilizzando (indipendentemente dal fatto che il tipo di base fosse un declare class o un normale class), il compilatore genererà tutto il codice per collegare la catena di prototipi e i costruttori di inoltro e cosa no.

Se si tenta di ereditare da un declare class che avrebbe dovuto essere un'interfaccia, si verificherà un errore di runtime poiché il codice generato si riferirà a un oggetto senza manifestazione di runtime.

Viceversa, se si semplicemente implement un'interfaccia che avrebbe dovuto essere un declare class, sarà necessario reimplementare tutti i membri da soli e non si avvarrà di alcun riutilizzo del codice da parte del- essere la classe base e le funzioni che controllano la catena del prototipo durante il runtime rigetteranno il tuo oggetto come se non fosse un'istanza della classe base.

Per ottenere davvero nerd, se si dispone di uno sfondo C++, si può pensare a circa interface come typedef e declare class come extern dichiarazione di un costruttore che manca una definizione strettamente in questa unità di compilazione.

Da un lato puramente di consumo (scrittura del codice imperativo, non aggiungendo nuovi tipi), l'unica differenza tra interface e declare class è che non è possibile un'interfaccia new. Tuttavia, se si intende extend/implement uno di questi tipi in un nuovo class, è assolutamente necessario aver scelto correttamente tra interface e declare class. Solo uno di loro funzionerà.

Due regole che vi servirà bene:

  • è il nome del tipo di allineamento con una funzione di costruzione (qualcosa richiamabile con new) che è effettivamente presente in fase di esecuzione (ad esempio Date è, ma JQueryStatic non è) ? Se no, si desidera sicuramente interface
  • Mi occupo di una classe compilata da un altro file TypeScript o qualcosa di abbastanza simile? Se si, utilizzare declare class
+0

In realtà è possibile creare una nuova interfaccia in dattiloscritto. L'unica limitazione è l'ereditarietà. –

+2

Non è possibile richiamare l'operatore 'new' su un tipo di interfaccia. Tuttavia, le interfacce possono avere costrutto firme, il che significa che è possibile richiamare l'operatore 'new' su un valore del tipo di interfaccia. Questo è molto diverso da come funziona 'class', dove la firma del costrutto si trova sul nome del tipo stesso piuttosto che su un'espressione di quel tipo. –

+0

Se si procede con l'aggiunta di un costruttore a un'interfaccia, dovrebbe essere l'UNICO membro dell'interfaccia, ad eccezione di "statici" della classe. Non combinare l'interfaccia della funzione di costruzione con l'interfaccia dell'oggetto costruito. Se lo fai, il sistema dei tipi ti permette di usare la stupidità come: nuovo (nuovo x()), dove x: Interfaccia. –

12

È possibile implementare l'interfaccia:

class MyClass implements Example { 
    Method() { 

    } 
} 

considerando che la sintassi declare class è davvero destinato ad essere utilizzato per aggiungere definizioni del tipo di codice esterno che non è scritto a macchina - quindi l'implementazione è "altrove".

+0

Quindi stai suggerendo che la classe declare debba essere usata per descrivere il codice non scritto in TypeScript? Presumo che il caso, ma nel file jquery.d.ts archiviato, JQueryStatic è un'interfaccia implementata da: dichiarare var $: JQueryStatic Avrei comunque se questo fosse dichiarare classe $ { statico pubblico .. } – Chris

+0

L'unica ragione per cui posso pensare a questo sarebbe se non volessi che le persone estendessero la classe - l'uso dell'interfaccia significa che dovresti fornire l'intera implementazione. – Fenton

+0

Ha senso. Forse quella era la ragione. – Chris

3

In parole povere, declare viene utilizzato in .ts/d.ts file per dire al compilatore che dovremmo aspettarci la parola siamo declaring di esistere in questo ambiente, anche se non è definito nel presente file. Questo ci permetterà quindi di avere sicurezza del tipo quando usiamo l'oggetto dichiarato, poiché il compilatore Typescript ora sa che qualche altro componente può fornire quella variabile.

Problemi correlati