2015-05-12 4 views
9

Знаете ли вы, если это возможно, чтобы получить массив интерфейсов, реализованных в классе с использованием декоратора:Использование декоратора, чтобы получить список реализованных интерфейсов

interface IWarrior { 
    // ... 
} 

interface INinja { 
    // ... 
} 

Так что если я что-то вроде:

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

Во время выполнения Ninja будет содержать аннотацию, содержащую ["INinja", "IWarrior"]?

Благодаря

+1

Интересно! Как я это читаю, но это только параметры (не интерфейсы и т. Д.)? По-видимому, будет невозможно достичь того, что вы хотите сделать, потому что интерфейсы отбрасываются. Я постараюсь как можно скорее взглянуть на это дальше. – Nypan

+0

Спасибо, я не уверен, потому что эта тема не очень хорошо документирована. Я продолжил исследование и задал некоторые вопросы, связанные с этим вопросом, на https://github.com/Microsoft/TypeScript/issues/3148, если вы хотите следить за прогрессом в этом вопросе. –

+0

Я немного посмотрел на это и протестировал его довольно много. Моему обновленным ответом для объяснений и примеров. – Nypan

ответ

3

В настоящее время типы используются только во время разработки и компиляции. Информация типа не переводится каким-либо образом в скомпилированный код JavaScript. Но вы тем не менее можете передать список строк параметрам декоратора следующим образом:

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

Спасибо за ваш ответ. Хотя это решение решает мою проблему, я считаю, что можно добиться такого же результата без необходимости вручную объявлять интерфейсы как строки. Компилятор должен иметь возможность генерировать эти аннотации, используя флаг -emitDecoratorMetadata. Я буду ждать больше ответов, и если это окажется невозможным, я дам вам очки. –

+0

Только для справки --emitDecoratorMetadata не работает для интерфейсов, на данный момент работает только для классов и примитивов. Поскольку реализация связана с интерфейсами, мы не можем получить доступ к этой информации во время выполнения. –

2

Поскольку вся информация об интерфейсах выбрасывается во время компиляции, это не будет возможно. Невозможно реализовать somedecorator для доступа к информации, которая была выбрана компилятором.

Передача имен интерфейсов декоратору в виде строк возможна, однако это не так полезно, поскольку вся информация, предоставленная интерфейсами, будет отсутствовать во время выполнения.

Хороший переполнение стека вопрос о реализации декораторов:

How to implement a typescript decorator?

Edit:

Таким образом, после исследования этого на некоторое время ответ на ваш вопрос до сих пор нет. По два причинам:

  1. Никакой информации об интерфейсах не может быть доступна после того, как время компиляции (с или без декораторов)
  2. Декораторов не получить доступ к наследуемым свойствам класса.

примеры Som для иллюстрации этого:

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; 
    } 
} 

Это приведет к скомпилированного кода (с --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); 

Любая информация, которая будет доступна нам в декоратор (кроме класса он сам) содержится в части __decorate:

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

В настоящее время информация о наследовании или интерфейсах не передается вместе с декораторами. Все декораторы для класса делают, украшают конструктор. Это, вероятно, не изменится, конечно, не для интерфейсов (поскольку вся информация о них отбрасывается во время компиляции).

Как мы можем выделить массив типов __metadata, мы получаем информацию о типе для String, Number и класса SomeClass (аргументы конструктора). Но интерфейс ISomeOtherInterface отображается как Object, потому что в компилируемом javascript не сохраняется информация о интерфейсах типов. Таким образом, лучшая информация, которую мы можем получить, это Object.

Вы можете использовать что-то вроде https://github.com/rbuckton/ReflectDecorators для лучшей работы с декораторами, но вы по-прежнему сможете получить доступ к информации в __decorate и __metadata.

Итак, подведем итоги.В декораторе нет информации о наследовании или интерфейсах для класса. Интерфейсы, вероятно, никогда не будут доступны для декоратора (или где-либо еще в скомпилированном коде).

+0

Спасибо за ваш ответ и исследования. Я очень ценю это. Извините, я не мог дать вам очки, потому что я изначально обещал, что если бы не было доступа к интерфейсам, я бы назвал другой ответ действительным. –

 Смежные вопросы

  • Нет связанных вопросов^_^