Unexpected Error with Angular Abstract Class Definition

I've encountered a peculiar Type Error while working with Abstract Classes in Angular 16.

Error: Uncaught (in promise): TypeError: this.httpService.get is not a function

Could it be that my interpretation of using Abstract Classes is off? Everything seems to function properly when I remove the Abstract class and directly call the http.service.

Models/HttpResponse.ts

export class HttpResponse {
  status: string | undefined;
  data: any;
  success: string | undefined;
  message: string | undefined;
}

Services/http.abstract_service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
    providedIn: 'root'
})

export abstract class AbstractHttpService {
    public abstract get(url: string): Observable<any>;
    
}

Services/http.service.ts

import { AbstractHttpService } from './http.abstract_service';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpResponse } from '@models/http_response';

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})

export class HttpService implements AbstractHttpService {

    constructor(private http: HttpClient){ }


    // GET Request
    get(url: string): Observable<any> {


        return this.http.get(url, {observe: 'response'}).pipe(
            map((res: any) => {
                let responseBody = res?.body;
                let result: HttpResponse;
                if(res){

                    result = { 
                        status: res.status, 
                        data: responseBody.data,
                        success: responseBody.success, 
                        message: responseBody.message
                    }
                }
                else {
                    console.log(`Error! HttpStatus: ${res.status}`);
                }

                return result;
            }));
    }

Services/data.service.ts

import { Injectable } from '@angular/core';
import { AbstractHttpService } from './http.abstract_service';
import { HttpResponse } from '@models/http_response';

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';


@Injectable({
    providedIn: 'root'
})

export class DataService {
    constructor( private httpService: AbstractHttpService ){ }

    getMyData(): Observable<HttpResponse> {

        const url = `${MyApiUrl}/Data`;

        // This is where the issue arises. When specifying the type as HttpService instead of using the abstract class, everything works.
        const response = this.httpService.get(url);

        return response;
        
    }

Pages/my/my.component.ts

import { Component, OnInit } from '@angular/core';
import { Result } from '@models/result';
import { DataService } from '@services/data.service'
import { HttpResponse } from '@models/http_response';

@Component({
  selector: 'app-my',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.scss']
})


export class MyComponent implements OnInit {

  dataSource: Result[] = [];

  constructor(private dataService: DataService) { }


   onGetMyData() {
    this.dataService.getMyData().subscribe((response: HttpResponse) => {

      console.log(`Status: ${response.status} Success: ${response.success} Data:`, response.data.results);

      response.data.results.forEach((val: any) => {
        this.dataSource.push(Object.assign({}, val))
      });

    });
  }

  async ngOnInit() {
    await this.onGetMyData();
  }


}

Any assistance would be greatly appreciated!

Answer №1

Consider utilizing the `extends` keyword instead of `implement`

export class HttpService extends AbstractHttpService

Answer №2

You might be confusing classes: using an abstract class instead of a class that implements it, which is why you're getting the error.

In Services/data.service.ts, make sure to import the http service class - Services/http.service.ts, not the abstract class -

Services/http.abstract_service.ts
:

Give this a try:

In Services/data.service.ts,

rather than:

import { AbstractHttpService } from './http.abstract_service';

constructor( private httpService: AbstractHttpService ){ }

use

import { HttpService } from './http.service';

constructor( private httpService: HttpService ){ }

edit

If you want to create a service with different implementations of an abstract class, you can use the abstract class as a token in providers and define the service that implements it:

providers: [ {provide:AbstractHttpService, useClass: HttpService } ]

For example, you can later switch to a different implementation:

providers: [ {provide:AbstractHttpService, useClass: SomeDifferentHttpService } ]

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

Angular2 Uniqueness Validator: Ensuring Data Integrity

Within my Angular2 form field, I am trying to ensure that the inputted value does not already exist. The challenge lies in accessing instance members within my custom validator function, codeUnique(). Upon execution, "this" refers to either FormControl o ...

When using Angular, it is important to remember that calling `this.useraccount.next(user)` may result in an error stating that an argument of type 'HttpResponse<any>' cannot be used with a 'Useraccount' balance

When attempting to use this.useraccountsubject(user) to insert information upon login, I encountered an error: ErrorType: this.useraccount.next(user) then Error An argument of type 'HttpResponse' is not allowed against a balance of 'Userac ...

Issue with DIV element wrongly breaking on iPhone Safari and Chrome - fix verified

I am currently working on a basic web application, but I'm facing an issue that's proving to be quite puzzling. When viewed on Desktop Chrome with the display set to iPhone 12 Pro (although I have a 13 Pro), everything looks perfectly aligned in ...

What is the process for retrieving information from a retail outlet?

How can I retrieve data from the Vuex store using Vue.js? Below is my code: Vue.use(Vuex); export default new Vuex.Store({ modules: { data } }) data.js import axios from 'axios'; const state = { data: '' }; cons ...

Specify the correct type for the SVG component when passing it as a prop

Currently, I am in the process of constructing a button component: interface ButtonProps { startIcon?: ... <-- what should be the data type here? } const Button = ({startIcon: StartIcon}) => { return <button>{StartIcon && <Sta ...

Encountering Error: Unable to bind EventEmitter as it is not recognized as a valid property in Angular 8

I have been struggling with using EventEmitter in Angular and I can't seem to get it right. I'm new to Angular and it's all a bit confusing for me. I've checked other posts and it seems like I'm doing everything correctly! I'm ...

Unlocking Column Data Tooltips in Angular Datatables: A Step-by-Step Guide

I have a single datatable and was wondering how to implement tooltips for when hovering over table cells. I tried the following code snippet, which successfully populated the tooltips. However, I am interested in achieving the same functionality using Angu ...

Manipulate MySQL data in Node.js by storing it in a variable

Struggling to grasp the concepts of nodeJS/typescript and how to effectively save database query results into variables for return. Seeking assistance to solve the problem faced: Here is a method snippet that needs help: public getAllProducts(): ProductA ...

Typescript absolute imports are not being recognized by Visual Studio Code

Encountered a similar unresolved query in another question thread: Absolute module path resolution in TypeScript files in Visual Studio Code. Facing the same issue with "typescript": "^4.5.5". Here is the content of my tsconfig.json: { ...

ngx-bootstrap modal is not being hidden when tested

In my Angular application, I am working on writing integration tests for a component that includes an ngx-bootstrap modal. Within these integration tests, the component features a button that triggers a modal to appear. Within the modal, there is a "Save" ...

Having trouble accessing the database in Angular and Ionic through a provider on a Tabbed page

I created a Home page with tabs using Ionic 3 and Angular. The tabs are named Stats and Calc. When clicking on the Stats tab, it triggers the class/component stats.ts (displayed below). This component utilizes two providers: CropProvider and ContractProvi ...

Eliminate a specific choice from a drop-down menu in an Angular application

I am implementing a feature where clicking on a button adds more select drop downs. I want to ensure that the selected options in these new dropdowns do not duplicate any already chosen options. Below is the code snippet used for the select drop down: < ...

Issue: The function react.useState is either not defined or its output is not iterable

I'm facing an issue while programming in Next.js 13. Any help or suggestions would be greatly appreciated! Here are the relevant files: typingtext.tsx import React from "react"; export function useTypedText(text: string, speed: number, dela ...

Angular material table cell coloring

Here is my current setup: I have an array of objects like this: users : User []; average = 5; compareValue (value){ ...} And I am displaying a table as shown below: <table mat-table [dataSource]="users"> <ng-container matColumnDef= ...

Tips for effectively managing RxJS Observables when synchronization of data is crucial

Hopefully the topic is clear enough. I am relatively new to working with RxJS and Redux. Currently, I am developing an Angular 2+ application using Observables and NgRX store. Within the store, there are multiple sections. My goal is to extract propertie ...

"Encountering a problem when trying to display Swagger-Editor for the second

While integrating the swagger-editor package into my React application, I encountered an issue. The first time I fetch the Swagger specifications from GitHub, everything works perfectly and validates correctly. However, upon rendering it a second time, an ...

Sending data to templates in Angular 2 using @Input()

I can't seem to figure out what I'm doing wrong with my listing template. I am trying to make it more dynamic by passing parameters using []="" and @Input(). Here is an example: <div class="listing wrapper"> <div class="wrapper" ...

Creating TypeScript projects without the use of a conventional IDE or text editor

Due to restrictions in my workplace, I am unable to download or install any applications, regardless of my job duties. I am interested in migrating several web apps to Angular 2 using TypeScript. I am a C# developer in my free time and I find TypeScript ap ...

Guide on executing get, modify, append, and erase tasks on a multi-parameter JSON array akin to an API within Angular

I have a JSON array called courseList with multiple parameters: public courseList:any=[ { id:1, cName: "Angular", bDesc: "This is the basic course for Angular.", amt: "$50", dur: & ...

In the world of Typescript, object-based type inference reigns

I'm grappling with TypeScript to correctly deduce typing in the given code snippet: type Customer = { name: string } type Item = { price: number } const customerConfig = { action: () => [{name: 'Alice'}] as Customer[], } const item ...