Is it possible to efficiently structure intricate JSON data onto interfaces in TypeScript with the incorporation of observables?

I am currently working on creating a simple web news reader that relies heavily on the Google News API (). I have set up all the necessary services, models, etc. However, I am having difficulty mapping the data onto specific interfaces. The Google API returns data in the following format from one of its endpoints ('top-headlines'):

{
    "status": "ok",
    "totalResults": 38,
    "articles": [
       {
       "source": {
            "id": "the-new-york-times",
            "name": "The New York Times"
       },
      "author": null,
      "title": "Hong Kong Protesters Clash with Police Amid Fears of Mob 
       Violence - The New York Times",
      "description": "some description",
      "url": "https://www.nytimes.com/2019/08/11/world/asia/hong-kong- 
       protest.html",
      "urlToImage": 
      "https://static01.nyt.com/images/2019/08/11/world/11hongkong15/
       11hongkong15-facebookJumbo.jpg",
      "publishedAt": "2019-08-11T11:19:03Z",
      "content": "some content… [+751 chars]"
       },
      (...and many more articles)
    ]
}

My goal is to extract only the articles. While I know that I can access the articles by calling myvariablename.articles if I retrieve the data from the API like that, it doesn't seem right to me.

Initially, I tried mapping it using the rxjs map method. However, I encountered an error in the console stating that there was no property 'articles' in the Articles model. So, I created a response model and nested the articles as a property inside the response model (interface). Despite this, I faced the same error. Subsequently, I suspected that the issue might lie in the Observable method's definition, so I switched to Response but to no avail. Currently, I am encountering an error in my component where I am subscribing and utilizing the service method, which states: "Type Response[] is not assignable to type Article[]"

top-news.service.ts

(...import statements)

export class TopNewsService {

(...variable definitions such as URL omitted.)

  public getAll(): Observable<Response[]> {
    return this.httpClient
      .get<Response[]>(`${this.url}/${this.endpoint}?country=us&apiKey=${this.token}`)
      .pipe(
        map(response => response.articles),
        catchError(this.handleError)
      );
  }
(...error handling)
}

article.ts

export interface Article {
  source: {
    id: string;
    name: string;
  };
  author: string;
  title: string;
  description: string;
  url: string;
  urlToImage: string;
  publishedAt: string;
  content: string;
}

response.ts

import { Article } from './article';

export interface Response {
  status: string;
  totalResults: number;
  articles: Article;
}

top-news-component.ts

(...import statements)

export class TopNewsComponent implements OnInit {

  articles: Article[];

  constructor(private http: HttpClient, private topNewsService: TopNewsService) { }

  ngOnInit() {
    this.getAllProjects();
  }

  getAllProjects() {
    this.topNewsService.getAll().subscribe(data => {
      this.articles = data;
      console.log(this.articles)
    },
      (err: string) => {
        alert(err);
      });
  }
}

I am seeking a solution to efficiently map the data within the service, retrieval of only articles, and then assigning this data to a designated variable in the component with the specified type of Article[].

Answer â„–1

It appears that you are utilizing

this.httpClient.get<Response[]>

This indicates your expectation for Google to provide an array of Response. However, Google does not return an array but instead a single Response. Therefore, the correct syntax should be

this.httpClient.get<Response>

Considering you are attempting to map this response to an array of articles, the observable returned by your service should be an Observable<Article[]>, not an Observable<Response[]>. Thus, it should read as follows:

public getAll(): Observable<Article[]> {

Regarding the interface definition:

export interface Response {
  status: string;
  totalResults: number;
  articles: Article;
}

This interface is incorrect since a response does not contain just one article but rather an array of articles. Referencing the JSON structure:

{
  "status": "ok", // one status string
  "totalResults": 38, // one totalResults number
  "articles": [ // an **array** of articles
    ..
  ]
}

The correct interface should be adjusted to reflect the array of articles:

export interface Response {
  status: string;
  totalResults: number;
  articles: Article[];
}

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

Unlock the secrets of extracting video from a livestream and seamlessly transferring it to a local web server without the need

Hey there, I have this link: '' Although it's not a real link, entering it leads to a .m3u8 file for live video streaming. I attempted using this link in my Angular 6 app frontend, but encountered a cross-origin issue as the video is being ...

Introduce AngularJS version 2 for better web development

I'm facing an issue with using provide in Bootstrap, and here's my code snippet: import { NgModule, provide } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from &apo ...

After using apt to install tsc, I find myself in a dilemma on how to either delete or upgrade it

After realizing I was missing Typescript on my server, I attempted to run the 'tsc' command. However, I received a message suggesting I use 'apt install tsc' instead. Without much thought, I executed the command. Normally, I would insta ...

Recommendations for Organizing Multiple "Isolated" Applications Using MVC 5 and Angular 2

We are currently managing a large MVC 5 ASP.NET 4.5.1 web application that follows the concept of treating each page as its own application due to the vast areas it covers. The existing pages are built using JQuery, regular Javascript, and Handlebars templ ...

In Angular components, data cannot be updated without refreshing the page when using setInterval()

Here's the Angular component I'm working with: export class UserListComponent implements OnInit, OnDestroy { private _subscriptions: Subscription; private _users: User[] = []; private _clickableUser: boolean = true; constructor( priv ...

Identify potential interference with Sentry.captureMessage(...) or Sentry.captureException(...) functions within a JavaScript application, such as being obstructed by an ad-blocking extension

Overview Our Javascript application uses Angular and TypeScript, with Sentry.io for error reporting. If an error occurs, a custom modal allows users to leave a message, which should be sent to Sentry when they click submit. Issue We have noticed that mes ...

The MdIcon in Angular 2 Material that functions properly in one component is causing issues in another

After upgrading from ng2 rc4 with material2 alpha6 to ng2 rc5 with material 2 alpha7-2, I encountered a new error related to the usage of <md-icon> which was previously working fine. The error message that appears now is Observable_1.Observable.thro ...

Sluggish behavior detected in hybrid AngularJS and Angular application when accessed through Safari browser

Lately, I have embarked on the task of migrating an AngularJS application to Angular 4 using the upgrade module. Within my AngularJS directives, I am utilizing a third-party library (ngFlow) for file uploads via XMLHttpRequest.send(). Everything functions ...

The validators in the FormControl are inconsistently functioning, showing up where they shouldn't and sometimes failing to work where

I am currently developing a dynamic form in Angular that allows users to request any number of parts, generating rows of input fields for each part. Each part has specific required fields, some of which should only accept numbers. I have implemented valid ...

Breaking down an object using rest syntax and type annotations

The interpreter mentions that the humanProps is expected to be of type {humanProps: IHumanProps}. How can I properly set the type for the spread operation so that humanPros has the correct type IHumanProps? Here's an example: interface IName { ...

Steps for combining angular2-datatable with angularfire2 observable array:

Hey there! I am currently working on integrating angular2-datatable into my Angular 2 application. However, I have a query which is puzzling me: How can I transfer the array information from an angularfire2 observable to the data-table? Here is a screensho ...

prolonging inner interface created by supabase

Below is the Typescript interface that has been generated by Supabase export interface definitions { Users: { /** Format: uuid */ id: string; /** * Format: timestamp with time zone * @default now() */ created_at?: string; ...

Unable to globally override the default font in MUI theme

Objective: My goal is to customize the default font in MUI themes. Issue: Despite reviewing MUI documentation and conducting research on Stack Overflow, I am facing difficulty overriding a custom font globally across my theme. Theme setup: import { creat ...

How to Invoke a TypeScript Function in Angular 2 Using jQuery

Using the Bootstrap-select dropdown in Angular 2 forms with jQuery, I am attempting to call a Typescript method called onDropDownChangeChange on the onchange event. However, it seems to not be functioning as expected. import { Component, OnInit, ViewChi ...

Using a snapshot test with MenuItem from material-ui is not compatible with Jest

I am facing an issue while trying to perform a snapshot test with jest on a component that utilizes typescript, react, and material-ui. Specifically, the MenuItem component from material-ui is throwing an Invariant Violation: getNodeFromInstance: Invalid a ...

Is it Possible for Angular Layout Components to Render Content Correctly even with Deeply Nested ng-container Elements?

Within my Angular application, I have designed a layout component featuring two columns using CSS. Within this setup, placeholders for the aside and main content are defined utilizing ng-content. The data for both the aside and main sections is fetched fr ...

Splitting a td tag into multiple columns dynamically with Angular

I am attempting to dynamically split the table element into separate columns. My desired layout should resemble this: The values for name and surname are fixed at 1, but the values for subjects and grades can vary (there may be 2 or more columns). Below ...

Tips for launching an angular 2/4 application on web hosting

After successfully creating a local copy of my Angular 4 project, everything is running smoothly on my computer. Now, I am looking to deploy the Angular application onto my shared web hosting in order to make it accessible globally. What steps should I t ...

Preserve Angular 2 service instances while navigating between routes

I am faced with a scenario where I have three components that are all utilizing the same DataService. This is not because they share the same data, but rather because they use the exact same methods and patterns: @Component({ templateUrl: './data ...

Issues with accessing view variables within a directive query are persisting

I am struggling with a specific directive: @Directive({ selector: '[myDirective]' }) export class MyDirective implements AfterViewInit { @ViewChild('wrapper') wrapper; @ViewChild('list') list; ngAfterViewInit() { ...