0

I have '@typescript-eslint/prefer-readonly-parameter-types': error set in my eslintrc file for my Angular project. To make this rule more easily enforceable, I have a DeepReadonly<T> monadic type defined to wrap objects to make them readonly.

Now, if I want to inject MyService into MyComponent without violating the lint rule, I have to set up MyComponent's constructor like this:

constructor(private readonly myService: DeepReadonly<MyService>)

This isn't enough, though, as I get this error when I try to build: No suitable injection token for parameter 'myService' of class 'MyComponent'. Consider using the @Inject decorator to specify an injection token.

That seems to be a good suggestion, as now everything builds fine when I change the constructor to:

constructor(@Inject(MyService) private readonly myService: DeepReadonly<MyService>)

However, since I am injecting this service into multiple components, I'd rather not have to use the @Inject decorator every time. Is there a way to force the provider for this service (or, ideally, any service) to use DeepReadonly<MyService> whenever there is a request to have MyService injected, assuming it's not possible or unsafe to manually create a new instance of MyService?

I'd like to be able to do something like this in AppModule, but it doesn't work:

@NgModule({
  declarations: [
    AppComponent,
    ...
    MyComponent,
  ],
  imports: [
    ...
  ],
  providers: [
    ...
    { provide: MyService, useClass: DeepReadonly<MyService> } // TS2693: 'DeepReadonly' only refers to a type, but is being used as a value here
  ],
  bootstrap: [AppComponent],
...
})
Tanner
  • 93
  • 1
  • 1
  • 11

3 Answers3

1

Due to the way dependency injection works, I think you'll likely have to either:

  1. use @Inject every time; or
  2. use something like class DeepReadOnlyMyService extends MyService { ... }; or
  3. possibly find a way to re-work MyService such that the deeper properties are already readonly.
Jason Verber
  • 484
  • 3
  • 5
0

Configure the provider using a factory: useFactory

Eddie Paz
  • 2,219
  • 16
  • 11
0

Use MyService instead of using DeepReadonly on the constructor. You should get your MyService on your component's constructor directly like below:

constructor(private myService: MyService)
Abdus Salam Azad
  • 5,087
  • 46
  • 35