6

I'm having a library called Themex.

//envInjector.ts
    import {InjectionToken} from "@angular/core";
    export const ENVIRONMENT = new InjectionToken<{[key: string]: any}>('ENVIRONMENT');

//themex.module.ts

import {ENVIRONMENT} from "./envInjector";
 
    
    @NgModule({
      declarations: [
    ThemexComponent,
    ModalComponent,
    UploadComponent,
    AlertComponent,

  ],
  imports: [
    CommonModule
  ],
  exports: [
    ThemexComponent,
    ModalComponent,
    UploadComponent,
    AlertComponent,
  ],
  providers: []
})

export class ThemexModule {
  static forRoot(config: {[key: string]: any}): ModuleWithProviders<any> {
    return {
      ngModule: ThemexModule,
      providers: [
        {
          provide: ENVIRONMENT,
          useValue: config
        }
      ]
    };
  }

}

The library is imported into an angular project inside the same angular workspace.

import {ThemexModule} from "themex";

If I'm importing it as given above I get an error.

"A value for 'forRoot' cannot be determined statically, as it is an external declaration. "

However, if I'm importing it as given below, everything seems to work.

import {ThemexModule} from "../../../themex/src/lib/themex.module";

I'm using

Angular CLI: 12.0.5
Node: 14.16.1

My Compiler Options. tsConfig.json enter image description here

All the errors are when I'm doing an ng serve. I haven't tried build.

harikrish
  • 2,009
  • 3
  • 19
  • 37
  • 1
    What if you edit `tsconfig.json` and update paths object `themex: ["projects/themex/src/public-api"]` (remove `dist`). Do you get the same error? – Prabh Sep 25 '21 at 21:37

2 Answers2

10

I've had this problem the last few days, and think I've found the solution. For me, it occurred when I was upgrading the dependencies on some of our libraries from Angular 10.

Our solution was making sure that the ModuleWithProviders return type was strongly typed for the module, so in your case:

export class ThemexModule {
  static forRoot(config: {[key: string]: any}): ModuleWithProviders<ThemexModule> {
    [...]
}
Carter Musick
  • 339
  • 3
  • 12
-1

Correct! Providing the signature is a must specially if/when the Ivy flag is on, full, or partial.

If you don't have a forRoot() or forChild() you don't need to worry about ModuleWithProviders. If you do, then return the type.

This is for when the publishable library is pushed to npm and others pull it in.

export class SomeModuleModule {
  static forRoot(...): ModuleWithProviders<SomeModuleModule> {...}
}
{
  "angularCompilerOptions": {
    "enableIvy": true,
    "compilationMode": "partial"
  }
}
Val Neekman
  • 17,692
  • 14
  • 63
  • 66