为啥 Angular AoT 不支持装饰器中的函数表达式?

Posted

技术标签:

【中文标题】为啥 Angular AoT 不支持装饰器中的函数表达式?【英文标题】:Why Angular AoT don't supports function expressions in decorators?为什么 Angular AoT 不支持装饰器中的函数表达式? 【发布时间】:2019-04-08 17:50:15 【问题描述】:

如果您尝试在装饰器中进行调用,Angular AoT 编译器会抛出错误。

考虑以下代码:

export function factoryBuilder(config: MyConfig) 
  return function customFactory() 
    return new MyService(config);
  ;


@NgModule()
export class MyModule 

  static forRoot(config: MyConfig): ModuleWithProviders 

    return 
      ngModule: MyModule,
      providers: [
        
          provide: MyService,
          useFactory: factoryBuilder(config),
        ]
    ;
  

如果您尝试使用 aot 标志 (--prod) 构建它:

编译器说:

ERROR in Error during template compile of 'AppModule'
  Function expressions are not supported in decorators in 'MyModule'
   ...
    Consider changing the function expression into an exported function.

有人可以从技术上解释为什么编译器不能支持吗?

PS:此代码在 JiT 模式下工作。

【问题讨论】:

可以用'export const myFactory ...'修复吗? 不,没关系。我改变它。 ty 【参考方案1】:

模块不支持箭头函数(或 lambda),因为 AOT 编译器需要能够“静态”分析模块。

使用普通的function 代替箭头函数应该可以解决问题:

export function myFactory(config)  ;

您可能还必须对myFactory 返回的customFactory 函数执行相同的操作。

您可以在official guide 或此cheat sheet 中找到有关 AOT 工作原理的更多信息。

【讨论】:

问题不在于语法。即使您使用函数语法重写,编译器也会抱怨。问题在于使用高阶函数 (en.wikipedia.org/wiki/Higher-order_function) 。我的问题是知道这样做是否在技术上是不可能的以及为什么。 ty 我必须承认我不知道高阶函数的答案。我刚才在我的应用程序中结束了复制一些代码而不是生成它,并且我最大程度地避免了这些高阶函数 您能否对您的第一句话进行更深入的介绍?我了解什么是静态,但不知道为什么它不首先转换,也不知道为什么它在装饰器中特别重要——否则 lambda 被允许在所有地方使用(实际上被转换为静态功能取决于您的 angular-cli 构建目标)

以上是关于为啥 Angular AoT 不支持装饰器中的函数表达式?的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使模板访问私有属性,Angular AOT 也会编译?

.Net 7 的Native AOT为啥不支持反射,你知道吗

如何将装饰器中的变量传递给装饰函数中的函数参数?

Angular AOT Build:内部错误:未知标识符未定义

Python - 在装饰器中获取原始函数参数

使用 @ngtools/webpack 在 Angular 11 + Webpack 4 中实现 AOT