Angular 4 AOT编译器不支持mixins

Angular 4 AOT compiler does not support 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 {

}

如果我编译这段代码,编译器会抛出:

Property 'ngClassControl' does not exist on type 'FooComponent'.

有什么想法吗?

编辑:既然有人问过,这里是另一个使用 TS 混入重现问题的例子,这次是在模板级别。

组件:

@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();
  // ...
}

错误:

ERROR in Error: Template parse errors: Can't bind to 'tag' since it isn't a known property of 'test'. ("][tag]="tag">")

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

我相信这是同样的问题。混合器的装饰器继承被破坏,因此目前您将不得不复制装饰属性。

这里的主要问题是 angular 编译器的功能有限。(在 the docs 中阅读更多内容)

AOT 编译器使用由 MetadataCollector 生成的元数据。它使用 typescript 对象模型(Node 的树)(这就是 AOT 只能与 typescript 一起使用的原因)来收集生成 ngfactory 所需的所有信息(在某些情况下还有 ngsummary) 文件。

您提供的示例与 AOT 编译器完全不同:

1) 自定义装饰器

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

Angular MetadataCollector will include @Mixin decorator in metadata of FooComponent symbol(item in decorators array) but it will be skipped when aot StaticReflector will call simplify since Mixin decorator is not registered in special map that includes only strictly defined decorators (source code)

此外,即使我们甚至将它包含在该映射中,它仍然不会在 aot 编译期间执行,因为它仅适用于支持的装饰器。

2) 调用自定义函数

export class HomePageComponent extends TaggedComponent(MyComponent) {

MetadataCollector will add TaggedComponent to metadata collection as symbol like {__symbolic: 'error', message: 'Symbol reference expected'}; but it also will be skipped 里面 StaticReflector.

据我所知,目前还没有支持它的解决方案。