What is the correct way to wrap an http.get in TypeScript?

My understanding of Typescript is limited, so I have a basic question related to my web application's frontend. In most http get-requests, I need to include two parameters. To simplify this process, I created a simple wrapper for HttpClient (from "angular/common/http") that automatically adds these parameters based on an object passed to it. Here is the current code snippet:

public get<T>(url: string, additionalObj?: AdditionalObject) {
  if (additionalObj == null) {
    return this.http.get<T>(url, {
      headers: {
        "Content-Type": "application/json",
      },
    });
  } else {
    const params: Record<string, string> = {};
    const param1: string | undefined = additionalObj?.param1;
    const param2: string | undefined = additionalObj?.param2;

    if (param1) {
      params["param1"] = param1;
    }
    if (param2) {
      params["param2"] = param2;
    }

    return this.http.get<T>(url, {
      headers: {
        "Content-Type": "application/json",
      },
      params,
    });
  }
}

Although this function works well in most cases, I also need to pass additional parameters in certain scenarios. However, I am unsure how to merge these additional parameters with the existing ones without modifying the functions that call my function. How can I achieve this without impacting the existing code?

Answer №1

It seems like your approach may be a bit complex for your current requirements. Have you considered utilizing Http Interceptors in Angular?

One point of confusion is that you always pass 2 parameters, but the initial condition (additionalObj == null) does not make use of these values. To address this, let's consider three scenarios:

  1. No Parameters provided
  2. Two Parameters supplied
  3. Two Parameters + Extra added

You can streamline this by creating a helper function to extract keys from an object and populate a record, reducing the need for multiple if checks.

GetParams(obj: any, params: Record<string, string>): Record<string, string>{
    for (const p of Object.keys(obj)){
      if(p){
        params[p] = obj[p];
      }
    }
    return params;
}

Now, tweak your wrapper method as follows:

 public get<T>(url: string, additionalObj?: AdditionalObject) {
    if (additionalObj == null) {
      return this.http.get<T>(url, {
        headers: {
          "Content-Type": "application/json",
        },
      });
    } else {
      let params: Record<string, string> = GetParams(additionalObj, {});
    
      return this.http.get<T>(url, {
        headers: {
          "Content-Type": "application/json",
        },
        params,
      });
    }
  }

}

This adjustment maintains functionality while enhancing cleanliness and scalability.

To include extra parameters, you have two choices:

  1. Update the existing properties of AdditionalObject. If modifying the object significantly is impractical, slightly revise the function signature for type safety by including additional parameters in additionalObj.

public get<T>(url: string, additionalObj?: Partial<AdditionalObject>)

  1. Add another object to the function call to handle these properties.

    public get<T>(url: string, additionalObj?: Partial<AdditionalObject>, evenMoreParams?: any) {
    if (additionalObj == null) {
      return this.http.get<T>(url, {
        headers: {
          "Content-Type": "application/json",
        },
      });
    } else {
      let params: Record<string, string> = GetParams(additionalObj, {});
      params = GetParams(evenMoreParams, params);
    
      return this.http.get<T>(url, {
        headers: {
          "Content-Type": "application/json",
        },
        params,
      });
    }
    

    }

    }

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

Tips on performing a join in an AngularFire2 database

I have been searching diligently but am still unable to find the correct answer. Any guidance towards the right direction would be greatly appreciated. My database contains information on users and projects: projects: 08177a0acb3f4d96f8cb5fa19002d2ed ...

Angular TSLint: Proceed to the following stage despite any encountered errors

I'm facing issues with TSLint in my Azure Devops Build Pipeline. Despite encountering lint errors, I need the build pipeline to proceed to the next step. How can I achieve this? Command Line: - script: | npm run lint > tsLintReport.txt ...

Notify programmers about the potential risks associated with utilizing certain third-party components

Incorporating a 3rd party library into our codebase involves utilizing its components directly, although some are enclosed within internally created components. Is there a method available to alert developers when they try to use one of the wrapped compone ...

Steps to disable TypeScript error messages for unused variables

I encountered an issue in my Angular CLI that says: jest.config.js is part of the TypeScript compilation but it's unused. Add only entry points to the 'files' or 'include' properties in your tsconfig. Additionally, I have a few o ...

Building dynamic input forms within Angular2

In order to customize the form for each guest, I aim to prompt users to provide their name, grade, and age for every guest they wish to invite. Initially, I inquire about the number of guests they plan to have. Subsequently, I intend to present a tailored ...

Encountering issues with compiling files in react app using webpack, failing to compile as anticipated

When it comes to compiling, I prefer using webpack with TypeScript files. In my webpack.config.js file: module.exports = async (env, options) => { const dev = options.mode === "development"; const config = { //Webpack configuration pr ...

Need to Resend SMS Verification in Angular4 Firebase Phone Authentication? Here's How!

Currently, I am developing a project using angular 4 and ionic 3. One of the features in my project is implementing firebase phone authentication for the login page. While working on this, I encountered the need to add a functionality to resend OTP when ...

How can we incorporate methods using TypeScript?

I'm currently diving into TypeScript and encountering some challenges when trying to incorporate new methods into the DOM or other pre-existing objects. For instance, I'm attempting to implement a method that can be utilized to display colored te ...

Issue: The data type 'void' cannot be assigned to the data type 'ReactNode'

I am encountering an issue while calling the function, this is just for practice so I have kept everything inside App.tsx. The structure of my class is as follows: enum Actor { None = '', } const initializeCard = () => { //some logic here ...

Preserve the checkbox state upon refreshing the page

I am facing an issue with keeping the checkbox state saved after a page reload. Currently, I have stored my unchecked checkboxes in localStorage, but I am unsure about what steps to take next. In simple terms, I want the checkbox to remain unchecked when I ...

What is the best way to ensure that the first tab is always pre-selected among dynamic tabs?

I'm currently working on an angular 4 project and I need to implement a feature where there are three checkboxes. When the first checkbox is selected, a new tab should be dynamically created. So, if all three checkboxes are selected, there will be thr ...

Create a compilation of categories/interfaces based on a mapping

Imagine you have the following object: const ROUTES = { PAGE_NO_PARAMS: '/hello/page/two', PAGE_R: '/about/:id', PAGE_Z: '/page/page/:param/:id', PAGE_N: '/who/:x/:y/:z/page', } as const Can we create a set ...

The Typescript decorator is unable to access the property type within its own scope

I am currently in the process of developing a dependency injector for use in my VUE js project. Recently, I created an Inject decorator with the intention of accessing a property type. It was functioning perfectly fine yesterday, but now it seems that som ...

Verification of unique custom string

How can I ensure that a string follows the specific format of x.xx.xxxxx? The first character is mandatory, followed by a period, then two characters, another period, and finally any number of characters of varying lengths. ...

Struggling to compile your Angular 2 application in Visual Studio 2015?

After carefully following all the steps outlined in the VISUAL STUDIO 2015 QUICKSTART documentation, I have also gone ahead and installed the "Microsoft .NET Core 1.0.1 VS 2015 Tooling Preview 2", even though it was not specifically mentioned in the docume ...

Receive characteristics in component specification

Is there a way to pass the native attributes of an img element to a custom image component without explicitly defining each one, like alt, and have them all be applied to the img tag? Here is an example of what I mean: @Component({ selector: 'image ...

LightWeightChart: How do I incorporate a chart that resembles this style?

Is it possible to create a chart using lightweight-chart that includes two graphs sharing the same x-axis but with different values on the y-axis? Essentially, I want to have two panes in a single chart. Does anyone have suggestions or tips on how this c ...

execute the node application using the .desktop file

Hello, I am attempting to launch an application in Linux by double-clicking it. I have come across the .desktop file as a solution (I need this method because the app will be deployed on a Raspberry Pi and users prefer not to use the terminal). Here is wha ...

The Angular 2 error message states that the type 'Observable<{}>' is not compatible with the assigned type

Observable is having trouble being assigned, my package.json file contains "angular2": "2.0.0-beta.17", "systemjs": "0.19.24", "es6-promise": "^3.0.2", "es6-shim": "^0.35.0", "reflect-metadata": "0.1.2", "rxjs": "5.0.0-beta.6", "zone.js": "0.6.12" The is ...

Using React to iterate through the child components of the parent

I have created a component that can accept either a single child or multiple children. Here is an example with multiple children: <SideDataGridItem> <div id='top'> <div>A1</div> <div>B1</div> ...