Qual è la differenza tra “declare class” e “interface” in TypeScript

In TypeScript, quando si creano i file di dichiarazione di origine .d.ts, che è preferibile e perché?

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 devi usare una class per quello. Entrambi non producono alcun output JS, quindi forse non importa?

interface è per quando vuoi semplicemente descrivere la forma di un object. 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 class a seconda che abbia o meno una clausola implements .

declare class è per quando si desidera descrivere una class esistente (di solito una class TypeScript, ma non sempre) che sarà presente esternamente (ad esempio, si hanno due file .ts che compilano in due file .js ed entrambi sono inclusi tramite tag di script in una pagina Web). Se si eredita da una class utilizza extends (indipendentemente dal fatto che il tipo di base fosse una declare class o una class regolare) il compilatore genererà tutto il codice per colbind la catena di prototipi e i costruttori di inoltro e cosa no.

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

Viceversa, se si implement semplicemente un’interfaccia che avrebbe dovuto essere una declare class , si dovrà implementare nuovamente tutti i membri autonomamente e non si avvarrà di alcun riutilizzo del codice dall’aspirante class base e le funzioni che controllano la catena del prototipo durante il runtime rigetteranno il tuo object come se non fosse un’istanza della class base.

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

Da un lato di puro consumo (scrivendo codice imperativo, non aggiungendo nuovi tipi), l’unica differenza tra l’ interface e declare class è che non è ansible creare una new interfaccia. Tuttavia, se intendi extend / implement uno di questi tipi in una nuova class , devi assolutamente aver scelto correttamente tra l’ interface e declare class . Solo uno di loro funzionerà.

Due regole che ti serviranno bene:

  • Il nome del tipo è allineato con una funzione di costruzione (qualcosa di invocabile con una new ) effettivamente presente in fase di esecuzione (ad esempio, la Date è, ma JQueryStatic non lo è)? Se no , vuoi sicuramente interface
  • Ho a che fare con una class compilata da un altro file TypeScript o qualcosa di abbastanza simile? Se , usa declare class

È ansible implementare l’interfaccia:

 class MyClass implements Example { Method() { } } 

Mentre la syntax della declare class è pensata per essere utilizzata per aggiungere definizioni di tipo per codice esterno che non è scritto in TypeScript, quindi l’implementazione è “altrove”.

In parole .ts , declare è usato nei file .ts / d.ts per dire al compilatore che dovremmo aspettarci che la parola chiave che declaring di esistere in quell’ambiente, anche se non è definita nel presente file. Questo ci permetterà quindi di avere sicurezza del tipo quando usiamo l’object dichiarato, poiché il compilatore Typescript ora sa che qualche altro componente può fornire quella variabile.