Search code examples
angulardependency-injectionangular-module

Angular 2 provider is not working with useValue and function call to new


I am wondering why Angular 2 providers syntax isn't working when I want to provide a specific value via the useValue field.

For instance, in the app.module.ts I have

// Abstracted base class (since interfaces don't work with libraries and tsc)
export class Base {
  constructor(public bar:Bar) {
  }
}

export class Foo extends Base {
  constructor(public bar:Bar) {
    super(bar);
  }
}

export class Bar {
  hello = "world";
}

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
  ],
  providers: [
    {provide: Base, useValue: new Foo(new Bar())}
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Attempting this throws an error during ng build:

ERROR in Error encountered resolving symbol values statically. Calling function 'Foo', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol AppModule in /Users/tbeauvais/Code/example-sdk/src/app/app.module.ts, resolving symbol AppModule in /Users/tbeauvais/Code/example-sdk/src/app/app.module.ts

I am getting around this by simply using the field, useClass, and then specifying the parameters through deps like this:

...
providers: [
  Bar,
  {provide: Base, useClass: Foo, deps:[Bar]}
],
...

It works, it's just not ideal and I am wondering what I am missing here. Also, I don't want to have to inject Bar for no reason.

Any help would be greatly appreciated. Cheers!


Solution

  • I know the error sounds cryptic but at the end of the day it is not. Some configurations (usually the aot-cli ones) do not allow code that cannot be statically analyzed. In order to do that one has to export a function, just like the error states, like this

    create a ts file that looks like this

    export function UseClassFunction(){ return function() { return new Foo(new Bar());}} and then import that and use it on useValue

    {provide: Base, useValue: UseClassFunction}