2015-05-12 9 views
9

fai a sapere se è possibile ottenere la gamma di interfacce implementate da una classe utilizzando un decoratore:Utilizzando un decoratore ottenere l'elenco delle interfacce implementate

interface IWarrior { 
    // ... 
} 

interface INinja { 
    // ... 
} 

Quindi, se faccio qualcosa di simile:

@somedecorator 
class Ninja implements INinja, IWarrior { 
// ... 
} 

In fase di esecuzione Ninja avrà un'annotazione che contiene ["INinja", "IWarrior"]?

Grazie

+1

Interessante! Il modo in cui sto leggendo questo però è solo parametri (non interfacce, ecc)? Sembra che sia ancora impossibile raggiungere ciò che vuoi fare perché le interfacce vengono gettate via. Cercherò di guardarmi più lontano il prima possibile. – Nypan

+0

Grazie, non sono sicuro perché questo argomento non è davvero ben documentato. Ho continuato le ricerche e ho posto alcune domande relative a questa domanda su https://github.com/Microsoft/TypeScript/issues/3148 nel caso in cui si desidera seguire i progressi in questo. –

+0

L'ho guardato un po 'e l'ho testato parecchio. Se la mia risposta aggiornata per spiegazioni ed esempi. – Nypan

risposta

3

Attualmente, i tipi vengono utilizzati solo durante lo sviluppo e il tempo di compilazione. Le informazioni sul tipo non sono tradotte in alcun modo nel codice JavaScript compilato. Ma puoi comunque passare l'elenco di stringhe al parametro decoratore in questo modo:

interface IWarrior { 
    // ... 
} 

interface INinja { 
    // ... 
} 


interface Function { 
    interfacesList: string[]; 
} 

@interfaces(["INinja", "IWarrior"]) 
class Ninja implements INinja, IWarrior { 

} 

function interfaces(list: string[]) { 
    return (target: any) => { 
     target.interfacesList = list; 
     return target; 
    } 
} 

console.log(Ninja.interfacesList); 
+0

Grazie per la risposta. Mentre questa soluzione risolve il mio problema, credo che sia possibile ottenere lo stesso risultato senza dover dichiarare manualmente le interfacce come stringhe. Il compilatore dovrebbe essere in grado di generare queste annotazioni usando il flag --emitDecoratorMetadata. Aspetterò altre risposte e se non sarà possibile ti darò i punti. –

+0

Solo per riferimento --emitDecoratorMetadata non funziona per le interfacce al momento funziona solo per le classi e le primitive. Poiché l'implementazione è correlata alle interfacce, non è possibile accedere a tali informazioni in fase di esecuzione. –

2

Poiché tutte le informazioni sulle interfacce viene gettato via al momento della compilazione questo non sarà possibile. Non c'è modo per l'implementazione del somedecorator per accedere alle informazioni che sono state gettate via dal compilatore.

Passando i nomi di interfaccia al decoratore come stringhe è possibile, questo non è tuttavia utile poiché tutte le informazioni fornite dalle interfacce andranno perse in fase di esecuzione.

Una buona domanda di overflow dello stack su decoratori d'esecuzione:

How to implement a typescript decorator?

Edit:

Così, dopo la ricerca di questo per un po 'la risposta alla tua domanda è ancora no. Per due motivi:

  1. Nessuna informazione sulle interfacce è possibile accedere dopo il tempo di compilazione (con o senza decoratori)
  2. Decoratori non ottengono l'accesso alle proprietà ereditate di una classe.

esempi Som per illustrare questo:

function myDecorator() { 
    // do something here.. 
} 

interface INamed { name: string; } 

interface ICounted { getCount() : number; } 

interface ISomeOtherInterface { a: number; } 

class SomeClass { 
    constructor() { } 
} 

class Foo implements INamed { 
    constructor(public name: string) { }  
} 

@myDecorator 
class Bar extends Foo implements ICounted { 

    private _count: number; 
    getCount() : number { return this._count; } 

    constructor(name: string, count: number, public someProp: ISomeOtherInterface, public someClass: SomeClass) { 
     super(name); 
     this._count = count; 
    } 
} 

questo si tradurrà in codice compilato (con il flag --emitDecoratorMetadata):

function myDecorator() { 
    // do something here.. 
} 
var SomeClass = (function() { 
    function SomeClass() { 
    } 
    return SomeClass; 
})(); 
var Foo = (function() { 
    function Foo(name) { 
     this.name = name; 
    } 
    return Foo; 
})(); 
var Bar = (function (_super) { 
    __extends(Bar, _super); 
    function Bar(name, count, someProp, someClass) { 
     _super.call(this, name); 
     this.someProp = someProp; 
     this.someClass = someClass; 
     this._count = count; 
    } 
    Bar.prototype.getCount = function() { return this._count; }; 
    Bar = __decorate([ 
     myDecorator, 
     __metadata('design:paramtypes', [String, Number, Object, SomeClass]) 
    ], Bar); 
    return Bar; 
})(Foo); 

Qualsiasi informazione che sarà disponibile a noi in il decoratore (ad eccezione della classe stessa) è contenuto nella parte __decorate:

__decorate([ 
     myDecorator, 
     __metadata('design:paramtypes', [String, Number, Object, SomeClass]) 
    ], Bar); 

Allo stato attuale ora nessuna informazione sull'ereditarietà o le interfacce sono passate insieme ai decoratori. Tutto ciò che un decoratore per una classe fa è decorare il costruttore. Questo probabilmente non cambierà, certamente non per le interfacce (dal momento che tutte le informazioni su di esse vengono gettate via al momento della compilazione).

Come possiamo vedere nell'array di tipi di __metadata otteniamo le informazioni sul tipo per String, Number e la classe SomeClass (argomenti del costruttore). Ma l'interfaccia ISomeOtherInterface è segnalata come Object, questo perché nessuna informazione sulle interfacce typescript viene mantenuta nel javascript compilato. Quindi la migliore informazione che possiamo ottenere è Object.

È possibile utilizzare qualcosa come https://github.com/rbuckton/ReflectDecorators per lavorare meglio con i decoratori, ma sarà comunque possibile accedere alle informazioni solo in __decorato e __metadata.

Quindi per riassumere.Nessuna informazione sull'ereditarietà o le interfacce per una classe è disponibile in un decoratore. Le interfacce probabilmente non saranno mai disponibili per un decoratore (o in qualsiasi altro posto nel codice compilato).

+0

Grazie per la vostra risposta e la ricerca lo apprezzo molto. Mi dispiace di non averti dato de punti perché in origine avevo promesso che se non fosse stato possibile accedere alle interfacce avrei contrassegnato l'altra come valida. –

Problemi correlati