Creating Service Typed with Alternative Class Providers in Angular

I've been experimenting with using alternative class provider in Angular. To illustrate my issue, let me provide an example scenario. I have a service defined as follows:

export MyService {
  method() {
    // Some Code
  }
}

Now, I am creating a child service by extending the parent service like this:

export MyAnotherService extends MyService {
  anotherMethod() {
    // Some Code
  }
}

Next, I specify the provided services in the app module's configuration in the following manner:

{ provide: MyService, useClass: MyAnotherService }

Then, within my component, I'm injecting the parent service and attempting to call the additional method like so:

constructor(
  private service: MyService
) {}

ngOnInit() {
  this.service.method();
  this.service.anotherMethod(); // <- Typescript complains about this line.
}

While the application functions correctly without any errors in the browser, TypeScript raises a warning:

[ts] Property 'anotherMethod' does not exist on 'MyService'.

Is there a way to notify TypeScript that the anotherMethod actually exists?

Note: Although accessing this.service['anotherMethod']() resolves the issue, I am seeking a solution to make TypeScript recognize this method.

Answer №1

Successfully tackled the issue. Utilizing Inject is necessary in this scenario:

import { Inject } from '@angular/core';

Next, within the constructor:

constructor(
  @Inject(MyService) private service: MyAnotherService
) {}

This approach allows for MyAnotherService to be injected by MyService, while retaining the interface of MyAnotherService.

Answer №2

To tackle this issue, one can utilize the Inject method, as demonstrated in the asker's response.

constructor(service: MyService) {}

The use of type annotation is essentially a shorthand for:

constructor(@Inject(MyService) service: MyService) {}

The purpose of the Injectable decorator is clarified in this particular answer.

If the class token resolves to a different class instance upon injection, it can be typed accordingly:

constructor(@Inject(MyService) service: MyAnotherService) {}

This approach might indicate an XY problem; it is only suitable if MyService is stateful, and should function as a singleton, and is utilized as a MyService instance in one location that cannot be altered by the developer, but takes on the role of MyAnotherService elsewhere.

If not, two separate providers ought to be declared and applied where necessary:

providers: [MyService, MyAnotherService]

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The `Required<Partial<Inner>>` does not inherit from `Inner`

I stumbled upon a code snippet that looks like this: type Inner = { a: string } type Foo<I extends Inner> = { f: I } interface Bar<I extends Inner> { b: I } type O<I extends Partial<Inner>> = Foo<Required<I>> & B ...

Understanding TypeScript's noUnusedParameters compiler option clarifications

I'm currently investigating whether this issue qualifies as a bug prior to submitting it on GitHub. When the noUnusedParameters setting is activated, the TypeScript compiler will generate an error in scenarios like this: const foo = ['one' ...

Ensuring typescript req.user in Passport JS is always defined: Best practices

When utilizing Passport JS, the req.user within the route is considered potentially undefined. However, the middleware prior to my route method ensures that this scenario does not occur. How can I convey this information to TypeScript? Object may be &apos ...

Is now the ideal moment to implement Angular 4?

When considering using Angular 4 for an enterprise SAP system, is it better to stick with Angular 2 and wait for the final release of Angular 4? There have been rapid releases of Angular 4 that may affect our decision. (View changelog) Your suggestions ar ...

Limit function parameter types to object keys

Is it possible to constrain my function parameter to match the keys of an object? I want to achieve something similar to this: export const details = { x: { INFO_x: 'xxx' }, y: { I ...

The map.get method in Typescript can sometimes return undefined when the key belongs to an interface type

I am facing an issue with my main.ts file where I have a map structure with keys defined by the interface dr and values stored as strings. However, when attempting to retrieve a value from the map using the get method, it returns undefined. Below is the ...

Encountering issues with Angular 7 when running "ng serve --aot" after making a file change

When running "ng serve --aot" it succeeds the first time but fails after a file change with the following error: { // Package.json contents here } Any assistance on how to make "ng serve --aot" compile the code properly after every file change would be ...

Why is it that the images stored in my assets folder are only visible when the folder is located outside the src-folder?

I have encountered a strange issue in two separate ReactJS projects involving the display of images stored within an "assets" folder. It seems that these images can only be located and shown when the folder is placed outside of the source directory. What ...

aria-labelledby attribute fails to work properly with tab and arrow key navigation

I am a beginner in the world of ARIA accessibility. I have noticed that when I use the tab or left/right arrow keys, the screen reader NVDA reads certain elements as clickable, even though when I hover my mouse over them, they are read correctly. Currently ...

Incorporating JQuery Plugin into Angular 2 Component

Currently, I am attempting to incorporate a jQuery code snippet into a component that I acquired online. This is the specific component. Although I have successfully integrated the HTML and CSS into the code, I am encountering difficulties with loading th ...

Updating the style of an Angular component dynamically within a loop

In my component, I have a basic button that is being looped using *ngFor. Within this component, there is a function that adds the 'active' class to a button when it is clicked. The issue I am facing is that when I click on another button, the p ...

What to do when ngClass fails to apply the class?

Every time I attempt: <mat-form-field class="mat-form-field-invalid"> <mat-label>ID</mat-label> <input matInput [(ngModel)]="this.testData"> </mat-form-fi ...

Tips for accessing global variables in an Angular 2 Component

How can I access the Google API library from an Angular 2 module written in Typescript? Whenever I try to access (gapi), it returns undefined. Is there an NPM module available that functions as a Typescript library in Angular 2, or do I need to use the Jav ...

Limit the types of function parameters to only one option within a union type parameter

I have a collection of tuples that I can use to define variables: type KnownPair = ["dog", "paws"] | ["fish", "scales"]; const goodPair: KnownPair = ["dog", "paws"]; //@ts-expect-error you cannot mix them: const badPair: KnownPair = ["dog", "scales"]; I ...

"Using an indexer in TypeScript allows for direct access to object properties by simply specifying the key within

I have a requirement to access an object property using a string as the key interface MyObject { prop1: string; prop2: string; prop3: string; prop4: string; prop5: string; } let initialValues: MyObject; //I initialize some properties initialVa ...

What is the significance of using an empty @Injectable() decorator in Angular?

My experience with Angular development is not consistent. One thing I have come to understand about the @Injectable() decorator is that it signifies - this class can receive injected dependencies and not this class can be injected as a dependency I can ...

A guide to implementing typescript with Next.js getStaticProps

I have Next.js set up with the TypeScript feature enabled Currently, I am attempting to utilize the getStaticProps function following the guidelines outlined here: https://nextjs.org/docs/basic-features/typescript Utilizing the GetStaticProps type export ...

Getting a multidimensional array from JSON in Typescript: A step-by-step guide

Below is a sample of a JSON array containing information about cars. var cars = { "cars": { "john": [], "alex": [ "ford" ], "hilton": [], "martin ...

Encountered an error in NestJS/TypeORM: Unable to access the property 'createQueryBuilder' as it is undefined

When I call 'localhost:3000/contacts' using Postman, I receive an error that I cannot figure out. My backend is connected to a PostgreSQL database. TypeError: Cannot read property 'createQueryBuilder' of undefined at ContactsReposit ...

Utilizing Angular service in a separate file outside of components

In my library file product.data.ts, I have a collection of exported data that I need to update based on a value returned by a featureManagement service. Our team regularly uses this service and includes it in the constructor of any component using standard ...