Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - useFactory - Error function calls are not supported. Consider replacing the function or lambda with a reference to an exported function

I use Angular AOT compiler version 4.1.3

I have a component library that exports a factory method that is then used to provide a service:

export function libServiceFactory(itemId: string) {
  return (http: Http): LibService => {
    return new LibService(http, itemId);
  };
};

I compile the library with ngc successfully.

Then import the compiled library and I use the LibServiceFactory in the website's AppModule:

providers: [
  { provide: SERVICE_TOKEN, useFactory: libServiceFactory('foo'), deps: [Http] }
],

I compile the website with ng build and I get the following error:

ERROR in Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function (position 5:10 in the
original .ts file), resolving symbol libServiceFactory in C:/Projects/MyProject/code/MyWebsite/node_modules/@mylibrary/service.factory.d.ts, res
olving symbol AppModule in C:/Projects/MyProject/code/MyWebsite/src/app/app.module.ts, resolving symbol AppModule in C:/Projects/MyProject/code/MyWebsite/src/app/app.mod
ule.ts, resolving symbol AppModule in C:/Projects/MyProject/code/MyWebsite/src/app/app.module.ts

The error (position 5:10 in the original .ts file) points to the anonymous function from the factory method: return (http: Http): LibService => {

As additional information, the way I create and use the factory method is the same Angular suggesting in the official documentation regarding injection tokens.

Is my error the expected behavior? Or is there something wrong in my implementation?

like image 546
nest Avatar asked Oct 30 '22 05:10

nest


1 Answers

You cannot execute code inside metadata decorators (@Sth) So you don't have the right to execute the function libServiceFactory('foo').

If you want to have a factory (and some Service injection to get the HttpClient Service for example), AND in the same time give some paramtersb('foo' in your case). You have to use the following trick:

export const MyLibConfig = new InjectionToken<MyConfig>('MyLibConfig');

export interface MyConfig {
  p: number;
  msg: string;
}

export function serviceFactory(myConfig: MyConfig, http: HttpClient): MyService {
  const service = new MyService(http);
  service.myConfig = myConfig;
  return service;
}

then you can use :

      providers: [
        {
          provide: MyService,
          useFactory: serviceFactory,
          deps: [MyLibConfig, HttpClient]
        },
        {
          provide: MyLibConfig,
          useValue: {p:3, msg:'foo'}
        }
      ]
like image 182
Gauthier Peel Avatar answered Nov 15 '22 06:11

Gauthier Peel