Leverage rxjs/Typescript to transform an array nested within the data received from an external API

Exploring Typescript/Javascript is a new adventure for me, especially as I delve into the world of rxjs. Here's a snippet of code that I've been working with:

return this.http.get<IXenoCantoResponse>(`${this.corsAnywhereUrl}${this.xenoCantoApiBaseUrl}${this.formatSearchTerm(searchTerm)}${this.recordingLength}`)
  .pipe(
    map(o => ({
      numRecordings: o.numRecordings,
      numSpecies: o.numSpecies,
      page: o.page,
      numPages: o.numPages,
      recordings: o.recordings
    }))
  );

This code helps in mapping responses from a public API to an interface called IXenoCanto:

export interface IXenoCantoResponse {
    numRecordings: string;
    numSpecies: string;
    page: string;
    numPages: string;
    recordings: [];
  }

The part that catches my interest is within the recordings[]. I utilize the data from these recordings to generate URLs and incorporate them into another object:

data.forEach((element, index) => {
  let sub = element.sono['full'].substr(0, this.getPosition(element.sono['full'], '\/', 6));
  urls.push({
    id: index + 1,
    url: `${sub}${element['file-name']}`
  });

});

export interface IVoice {
  id: number;
  url: string;
}

Although this code fulfills its purpose, I'm constantly seeking ways to enhance its efficiency.

I've pondered whether it's feasible to directly map the response array of type any[] to IVoice[] in the initial mapping code. Thus, I attempted modifying the IXenoCantoResponse interface like this:

export interface IXenoCantoResponse {
    numRecordings: string;
    numSpecies: string;
    page: string;
    numPages: string;
    recordings: IVoice[]
  }

Subsequently, my aim was to map the [] response directly to IVoice[], something along the lines of:

return this.http.get<IXenoCantoResponse>(`${this.corsAnywhereUrl}${this.xenoCantoApiBaseUrl}${this.formatSearchTerm(searchTerm)}${this.recordingLength}`)
      .pipe(
        map(o => 
          o.recordings.map((element, index) => {

              id: index + 1,
              url: `${element.sono['full'].substr(0, this.getPosition(element.sono['full'], '\/', 6))}${element['file-name']}`
          
          })
      );

Thus far, my attempts in implementing this second approach have been unsuccessful. Perhaps, configuring the map operator with an array object poses a challenge. Can anyone provide guidance on how to proceed?

Edit:

Each object within the mentioned recordings array adheres to the following format:

        {
            "id": "477551",
            "gen": "Troglodytes",
            ...
        }

Answer №1

It is crucial to define the type of objects being created

return this.http.get<IXenoCantoResponse>(`${this.corsAnywhereUrl}${this.xenoCantoApiBaseUrl}${this.formatSearchTerm(searchTerm)}${this.recordingLength}`)
   .pipe(
      map(o => return new IXenoCantoResponse({
          numRecordings: o.numRecordings,
          numSpecies: o.numSpecies,
          page: o.page,
          numPages: o.numPages,
          recordings: o.recordings.map((element: IVoice, index) => new IVoice({
              id: index + 1,
              url: `${element['sono']['full'].substr(0, this.getPosition(element['sono']['full'], '\/', 6))}${element['file-name']}`
          })
        });
      }))
    );

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

I implemented progress bars in Angular 2 that have changing maximum values. The service updates the maximum value for each bar dynamically. Currently, the progress bars are functioning at 100% capacity

this.games=[ {"val":50, "name":"Articlescontributed","max":35}, {"val":30 ,"name":"Articlesrated", "max":999}, {"val":20, "name":"Views", "max":35}, {"val":30, "name":"Ratings", "max":35}, {"val":20, "name":"Follower", "max":200}, { ...

Tips for resolving the ExtPay TypeError when using Typscript and Webpack Bundle

I am currently trying to install ExtPay, a payment library for Chrome Extension, from the following link: https://github.com/Glench/ExtPay. I followed the instructions up until step 3 which involved adding ExtPay to background.js. However, I encountered an ...

The MUI datagrid fails to display any rows even though there are clearly rows present

Today, I encountered an issue with the datagrid in Material UI. Despite having rows of data, they are not displaying properly on the screen. This problem is completely new to me as everything was working perfectly just yesterday. The only thing I did betwe ...

Upgrading Angular from version 8 to 9: Dealing with Compilation Errors in Ivy Templates

After successfully upgrading my Angular application from version 8 to version 9 following the Angular Update Guide, I encountered some issues in the ts files and managed to resolve them all. In version 8, I was using the View Engine instead of Ivy, which ...

What steps should I take to address the numerous errors I am encountering in Atom using the Atom linter tool?

My Atom interface is showing the following errors: {Error running gjslint}(x4) {Error running selective}(x4) Upon checking the errors section, I found the following details: [Linter] Error running selective Error: ENOENT: no such file or directory, open ...

Is it considered bad form to utilize nearly identical for loops in two separate instances within Angular 6?

I am working on creating two lists for a roster. The first list will display the current members of this year, while the second list will show if individuals have been excused for this year. After analyzing my code, I realized that I am using two identic ...

Unable to modify the Jest mock function's behavior

The issue I am facing involves the following steps: Setting up mocks in the beforeEach function Attempting to modify certain mock behaviors in specific tests where uniqueness is required Encountering difficulty in changing the values from the in ...

The sequence of initializing test hooks in inconsistent playwright tests

My testing framework setup looks something like this: test.describe("...", () => { let p: Page; test.beforeEach(async({browser}) => { p = await (await browser.newContext()).newPage(); } test(...); test(...); test.aft ...

Struggling to retrieve posted data using Angular with asp.net

I have encountered an issue while sending a post request from Angular to my ASP.NET server. I am trying to access the values of my custom model class (SchoolModel) and I can see that all the values are correct inside Angular. However, when I attempt to ret ...

A method for comparing two arrays containing identical objects and then storing the results in a variable

I have an item stored within two other items called formKeyValues and form formKeyValues https://i.stack.imgur.com/nRfiu.png form https://i.stack.imgur.com/eDpid.png I am looking to extract only the keys and values from formKeyValues and place them in ...

Comprehending and interpreting a visible arrangement

I'm attempting to grasp the structure of observables and seeking guidance on locating the response, error, and complete sections. Additionally, I am curious about identifying the body and header parts in the response of a POST request. To gain insigh ...

establishing the default value as p-multiselect

Here is the code snippet I am currently working on: export class LkBoardStatus { id : number = 0; descr : string = ''; } In the component.ts file, I have defined the following: //... lkBoardStatusList: LkBoardStatus[] = []; selectedStat ...

Guide on exporting a function from a module as a class property

How to export a function as a class property from a module? Even if modifiers such as public are added, when a class property points to a function within a module, it behaves as though it is private. There are multiple ways to define a property (a, b, c ...

Can data be filtered based on type definitions using Runtime APIs and TypeDefs?

My theory: Is it feasible to generate a guard from TypeDefs that will be present at runtime? I recall hearing that this is achievable with TS4+. Essentially, two issues; one potentially resolvable: If your API (which you can't control) provides no ...

Using JavaScript to assign function arguments based on arbitrary object values

I am facing a challenge with a collection of arbitrary functions and a method that takes a function name along with an object or array of parameters to call the respective function. The issue arises from the varying number of inputs in these functions, som ...

Leveraging Global Variables in TypeScript with Node Express

Having issues using global variables in node express when working with typescript. Specifically, trying to use the same global array variable tokenList:tokList across multiple modules and middleware, but haven't been successful so far. Any suggestions ...

Creating specific union types for a bespoke React hook

There are 4 objects with both similar and different keys. The union of these objects is used for database operations as follows -> type Objects = Food | Diary | Plan | Recipe ; A Custom Pagination Hook function usePaginate (key: string, options: Option ...

Guidelines for creating a binary release of Node.js with native modules

Currently, I am in the midst of exploring the world of Node.js projects, delving into different bundlers and various other components. One interesting concept that came to mind is the idea of bundling Node.js into a single binary for Linux, macOS, or Windo ...

Modeling a potentially empty array in Typescript can be achieved by implementing specific interface definitions

Here is the current situation: type A = { b: string, c: number } I have an object that I will receive from an API, which could be either A[] or [] As of now, when I attempt to use it, const apiData: A[] || [] const b = apiData[0].a // I expected this to ...

TSX: Interface Definition for Nested Recursive Array of Objects

I'm having trouble making my typescript interface compatible with a react tsx component. I have an array of objects with possible sub items that I need to work with. Despite trying various interfaces, I always run into some kind of error. At the mome ...