Angular 4 Компилятор AOT не поддерживает mixins

Иногда я использую Mixins для ввода повторяющихся функций, таких как slugUrl().

Но он не работает с компилятором angular 4.

export function Mixin(decorators: Function[]) {
  return function (classFn: Function) {
    decorators.forEach(decorator => {
      Object.getOwnPropertyNames(decorator.prototype).forEach(name => {
        classFn.prototype[name] = decorator.prototype[name];
      });
    });
  };
}


@Mixin([BehaviorInjected])
export class FooComponent {

}

Если я скомпилирую этот код, компилятор выбрасывает:

Свойство 'ngClassControl' не существует в типе 'FooComponent'.

Любые идеи?

Изменить: поскольку был кто-то, кто спросил, вот еще один пример использования TS mixins, который воспроизводит проблему, на этот раз на уровне шаблона.

Компоненты:

@Component({
    selector: 'home-page',
    template: '<test [tag]="tag"></test>'
})
export class HomePageComponent extends TaggedComponent(MyComponent) {
    public tag = 'hi there';
}

@Component({
    selector: 'test',
    template: '<div></div>'
})
export class TestComponent extends TaggedComponent(MyComponent) {}

Примеси:

type Constructor<T> = new(...args: any[]) => T;

export function TaggedComponent<T extends Constructor<{}>>(Base: T) {
     class TaggedBase extends Base {
        @Input() tag: string;
     };

     return TaggedBase;
}

export class MyComponent {
    protected subscriptions: Subscription = new Subscription();
  // ...
}

Ошибка:

Ошибка в ошибке: ошибки анализа шаблона: не удается привязать к тегу, поскольку он не является известным свойством "теста". ( "] [Тег] =" тег " > " )

Ответы

Ответ 1

См. https://github.com/angular/angular/issues/19145

Я считаю, что это та же проблема. Наследование декоратора прерывается для миксинов, поэтому в настоящее время вам придется дублировать оформленные свойства.

Ответ 2

Основная проблема заключается в том, что компилятор angular имеет ограниченную функциональность. (читайте больше в docs)

Компилятор AOT использует метаданные, созданные MetadataCollector. Он использует объектную модель typescript (дерево Node) (, почему AOT может использоваться только с typescript), чтобы собрать всю информацию, необходимую для создания ngfactory (в некоторых случаях также ngsummary).

Приведенные вами примеры совершенно различны для компилятора AOT:

1) Пользовательский декоратор

@Mixin([BehaviorInjected])
export class FooComponent {}

Angular MetadataCollector будет включать декоратор @Mixin в метаданных <<26 > (элемент в массиве decorators) но будет пропущен, когда aot StaticReflector вызовет simplify, так как Mixin декоратор не зарегистрирован на специальной карте, которая включает только строго (исходный код)

Более того, если мы даже включим его в эту карту, он все равно не будет выполнен во время компиляции aot, потому что он доступен только для поддерживаемых декораторов.

2) Вызов пользовательской функции

export class HomePageComponent extends TaggedComponent(MyComponent) {

MetadataCollector добавит TaggedComponent в коллекцию метаданных как символ типа {__symbolic: 'error', message: 'Symbol reference expected'};, но также будет пропущен внутри StaticReflector.

И насколько я знаю, в настоящее время нет решения для его поддержки.