typescript - Använda en dekoratör för att få en lista över implementerade gränssnitt
Vet du om det är möjligt att få arrayen av gränssnitt som implementeras av en klass med en dekorator:
interface IWarrior {
// ...
}
interface INinja {
// ...
}
Så om jag gör något som:
@somedecorator
class Ninja implements INinja, IWarrior {
// ...
}
Vid körning kommer Ninja att ha en annotation som innehåller ["INinja", "IWarrior"] ?
Tack
Svar #1
För närvarande används typer endast under utveckling och kompileringstid. Typinformationen översätts inte på något sätt till den kompilerade JavaScript-koden. Men du kan dock skicka listan med strängar till dekoratorparametern på detta sätt:
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);
Svar #2
Eftersom all information om gränssnitt kastas bort vid kompileringstid kommer detta inte att vara möjligt. Det finns inget sätt för implementeringen av somedecorator att få tillgång till information som har kastats bort av kompilatorn.
Att skicka gränssnittsnamnen till dekoratorn som strängar är möjligt, detta är dock inte så användbart eftersom all information som tillhandahålls av gränssnitten kommer att försvinna vid körning.
En bra fråga på Stack Overflow om att implementera dekoratörer:
Hur implementerar man en TypeScript-decorator?
Redigera :
Så efter att ha forskat på detta ett tag är svaret på din fråga fortfarande nej. Av två skäl:
- Ingen information om gränssnitt kan nås efter kompileringstid (med eller utan dekoratorer)
- Dekoratörer får inte tillgång till de ärvda egenskaperna hos en klass.
Som exempel för att illustrera detta:
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;
}
}
Detta kommer att resultera i kompilerad kod (med flaggan --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);
All information som kommer att vara tillgänglig för oss i dekoratören (förutom klassen själv) finns i __decorate-delen:
__decorate([
myDecorator,
__metadata('design:paramtypes', [String, Number, Object, SomeClass])
], Bar);
Som det ser ut nu överförs ingen information om arv eller gränssnitt till dekoratörerna. Allt en dekoratör för en klass gör är att dekorera konstruktören. Detta kommer förmodligen inte att ändras, åtminstone inte för gränssnitten (eftersom all information om dem kastas bort vid kompilering).
Som vi kan se i typarrayen av __metadata får vi typinformationen för String, Number och klassen SomeClass (konstruktörsargument). Men gränssnittet ISomeOtherInterface rapporteras som Object, detta beror på att ingen information om TypeScript-gränssnitt behålls i den kompilerade JavaScript. Så den bästa information vi kan få är Object.
Du kan använda något som https://github.com/rbuckton/ReflectDecorators för att bättre arbeta med dekoratorer, men du kommer fortfarande bara kunna komma åt informationen i __decorate och __metadata.
Så för att sammanfatta. Ingen information om arv eller gränssnitt för en klass är tillgänglig i en dekoratör. Gränssnitt kommer sannolikt aldrig vara tillgängliga för en dekoratör (eller någon annanstans i den kompilerade koden).
