Angular doesn't support this particular type as an injection token

I'm attempting to create a constructor with a type of string, but I keep encountering the following error:

This particular type is not supported as an injection token

@Injectable({providedIn: 'root'})
export class DataService {
     constructor(url:string, private http:HttpClient) { 
     }
}

export class PostService extends DataService {
    constructor(http:HttpClient) {
         super("https://jsonplaceholder.typicode.com/posts",http);
    }
 }

Answer №1

It appears that the issue you are facing is as follows: Compiled with problems:X

ERROR

src/app/services/data.service.ts:14:23 - error NG2003: No suitable injection token for parameter 'url' of class 'DataService'.
  Consider using the @Inject decorator to specify an injection token.

14   constructor(private url: string, private http: HttpClient) {}
                         ~~~

  src/app/services/data.service.ts:14:28
    14   constructor(private url: string, private http: HttpClient) {}
                                  ~~~~~~
    This type is not supported as injection token.

The DataService class (which is extended by PostService) should not be marked as injectable. Making a class injectable means it can be provided and injected as a dependency. However, this should not be done in this case as DataService serves the purpose of providing a shape or a reusable service to avoid duplication.

To resolve this issue, you can comment out the Injectable decorator in DataService:

// @Injectable({
//   providedIn: 'root',
// })

export class DataService {
  constructor(private url: string, private http: HttpClient) {}

The revised PostService code should look like this:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

import { DataService } from './data.service';

@Injectable({
  providedIn: 'root',
})
export class PostService extends DataService {
  constructor(http: HttpClient) {
    super('https://jsonplaceholder.typicode.com/posts', http);
  }
}

Answer №2

The main concern here is that when DataService is annotated with @Injectable, all constructor parameters must also be injectable, which means that primitive types like string cannot be injected. On the flip side, if PostService is not marked as @Injectable, it will not receive an injected instance of httpClient.

It seems like you don't want DataService to be injectable everywhere, right? Its purpose is to serve as an abstract class, correct?

If that's the case, then you should mark the concrete class(es) as @Injectable:

export abstract class DataService {
     constructor(url:string, private http:HttpClient) { 
     }
}

@Injectable({providedIn: 'root'})
export class PostService extends DataService {
     constructor(http:HttpClient) {
         super("https://jsonplaceholder.typicode.com/posts", http);
     }
 }

Answer №3

In my understanding, trying to use the constructor for dependency injection may not be effective in this scenario.

In Angular, subclassing components has always been a bit tricky and fragile, so it's best to avoid it if possible. Instead of inheriting, consider delegating or composing. (Edit: Upon further review, I see that this is not related to a component, my apologies)

However, if you still want to extend, the following approach may work better in your specific case:

export abstract class AbstractDataService {
  constructor(private http: HttpClient) {}

  /** Defined by subclasses. */
  protected abstract getUrl(): string;
}

@Injectable({ providedIn: 'root' })
export class PostService extends AbstractDataService {
  protected getUrl(): string {
    return 'https://jsonplaceholder.typicode.com/posts';
  }
}

Instead of passing the property through the constructor, provide it using an abstract method that you implement in your subclasses.

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

Issue: Catching errors in proxy function calls

I am currently using Vue 3 along with the latest Quasar Framework. To simplify my API calls, I created an Api class as a wrapper for Axios with various methods such as get, post, etc. Now, I need to intercept these method calls. In order to achieve this ...

What is the best way to emphasize when the path matches exactly with '/'?

Is there a way to highlight the path only when it exactly matches '/'? Currently, even on 'Page 2', the 'Home' link is still highlighted. Check out the plunker here .active { color: red; } <a routerLinkActive="active" r ...

Analysis of cumulative revenue using Palantir Foundry Function

I am in need of creating a function that can transform raw data into target data. The raw data consists of a table with columns for customer, product, and revenue, while the target data includes customer, revenue, and cumulative revenue. customer produ ...

Angular 2 fails to apply active class colors to tabs in a modal popup

https://i.sstatic.net/T8lIu.pnghttps://i.sstatic.net/O21ZO.pngIn my modal popup, I have multiple tabs in the modal body. The issue I am facing is that when the modal is invoked, the active tab color is not being applied. The modal itself is built using ngx ...

Observing changes in the DOM using Angular

Is there a way to programmatically track the changes of a DOM node? It can be time-consuming to detect the delta in the inspector, especially with angular components that have many class names. https://i.stack.imgur.com/ns6rR.png I am looking for a more ...

Typescript: The art of selectively exporting specific types

As I develop a Typescript component library, the API consists of two named exports: the component itself and a helper function to create an object for passing as a prop. The process is straightforward. For this library, I utilize an index.ts file as the m ...

Exploring Deeply Nested Routing in Angular

I've been exploring the use of multiple router outlets and encountered an issue. When using the navigateBy function of the router, I am unable to view my child route and encounter an error. However, when I access it via the routerLink in HTML, I get ...

Managing the onChange event for a MaterialUI dropdown component

I'm encountering an issue with validating the MaterialUI TextField component (Country list) wrapped with Autocomplete. I am trying to use the onChange event to enable the Submit button when the country field is filled in. However, the problem arises w ...

I'm curious if it's possible to superimpose a png image and specific coordinates onto a map by utilizing react-map

I am attempting to showcase a png graphic on a react-map-gl map, following the approach outlined here. Unfortunately, the image is not appearing as expected and no error messages are being generated for me to troubleshoot. Below is the snippet of code I&a ...

There was a Runtime Error that occurred, stating a TypeError: It is not possible to access properties of an undefined value (specifically

I've encountered an issue with a donut chart implemented from react-apex charts. Every time I try to render the page containing the chart, an error occurs. However, if I make changes to a property of the chart, it renders without any errors on the fro ...

Exploring the differences between initializing class members and using setters and getters in Typescript

Here is the code snippet that I am working with: export class Myclass { private _someVal = 2; public get someVal() { return this._someVal; } public set someVal(val) { this._someVal = val; } } In my template, I have <span&g ...

The attribute is not found on the combined type

After combing through various questions on stackoverflow, I couldn't find a solution to my specific case. This is the scenario: interface FruitBox { name: string desc: { 'orange': number; 'banana': number; } } interf ...

Mapping an array of keys to an array of properties using Typescript

Is there a way to achieve the following: type A = { a: string; b: number; c: boolean }; type B = ["b", "a"]; type C = MapProps<A, B> ?? // [number, string] The solution I have currently is: type C = {[key in B[number]]: A[key]} ...

Assets in production encountering a 404 error - distribution glitch

Once the base href URL is added to index.html <base href="."> I proceed to run production mode using "ng build --prod" After encountering a 404 Error, I moved the dist folder into the xampp htdocs folder and included an error image ...

Developing applications using the combination of Vue.js, JSX, and

While I have no issues using TypeScript with single file components (.vue files), I encountered problems when attempting to use it with JSX files. Two errors arise, one in my index.ts file. I'm uncertain if there was a mistake made in my configuration ...

Dealing with the "expression has changed after it was checked" error in Angular 2, specifically when a component property relies on the current datetime

My component's styling is dependent on the current datetime. I have a function within my component that looks like this: private fontColor( dto : Dto ) : string { // date of execution for the dto let dtoDate : Date = new Date( dto.LastExecu ...

Saving the compiled Angular dist folder in the artifactory repository

Our team utilizes Artifactory to manage libraries and artifacts. We have configured the npm registry to point to our Artifactory URL for library retrieval. GitLab is integrated into our CI pipeline. Specifically, I have implemented a job that compiles the ...

What is the correct placement for the "require("firebase/firestore");" code in my Angular 4 project?

After doing thorough research on the internet and carefully reading through the Firestore documentation, I am facing difficulties in converting my partially built Angular (4) project. Following the instructions in the "Get Started with Cloud Firestore" gu ...

Sending nested JSON in Angular 2 Post Request

Are there any efficient ways to handle the task of importing raw JSON data and posting it to a server using an import function? For example, if a user copies and pastes the following JSON: { "name": "testing", "design": [ { "name": "test", ...

Tips for utilizing an elective conversion by typing

In my opinion, utilizing code is the most effective approach to articulate my intentions: interface Input { in: string } interface Output { out: string } function doStuff(input: Input): Output { return { out: input.in }; } function f<Out>(input ...