简体   繁体   English

将 http 响应映射到类型参数中的对象数组

[英]mapping http response to object array in type argument

I wonder if someone can explain this error to me, since Im relatively new to angular, typescript and rxjs.我想知道是否有人可以向我解释这个错误,因为我对 angular、typescript 和 rxjs 比较陌生。

What I try to do is to map the server response I get for calling getHeroes() in a format that makes it easy for my components to consume it.我尝试做的是以一种格式映射我通过调用getHeroes()获得的服务器响应,以便我的组件可以轻松使用它。

This is my getHeroes() method that is working:这是我正在工作的getHeroes()方法:

  getHeroes(): Observable<Hero[]> {
    const heroes = this.http.get<any>(this.heroesUrl)
      .pipe(
        map((res: EmbeddedResponse) => res._embedded.heroes),
        tap(data => this.log('HeroService: fetched Heroes'),
          catchError(this.handleError<Hero[]>('getHeroes', []))
        ))
    return heroes
  }

Notice the any type argument in this.http.get<any>()注意this.http.get<any>()any类型参数

I would like to be more specific with the type argument in getHeroes() :我想更具体地使用getHeroes()的类型参数:

  getHeroes(): Observable<Hero[]> {
    const heroes = this.http.get<Hero[]>(this.heroesUrl)
      .pipe(
        map((res: EmbeddedResponse) => res._embedded.heroes),
        tap(data => this.log('HeroService: fetched Heroes'),
          catchError(this.handleError<Hero[]>('getHeroes', []))
        ))
    return heroes
  }

Notice the Hero[] type argument in this.http.get<Hero[]>()注意this.http.get<Hero[]>()Hero[]类型参数

But changing the type argument in getHeroes() from any -> Hero[] resolves in this Error:但是从any -> Hero[]更改getHeroes()的类型参数会解决此错误:

error TS2345: Argument of type 'OperatorFunction<EmbeddedResponse, Hero[]>' is not assignable to parameter of type 'OperatorFunction<Hero[], Hero[]>'.
  Property '_embedded' is missing in type 'Hero[]' but required in type 'EmbeddedResponse'.

The EmbeddedResponse interface looks like this: EmbeddedResponse 接口如下所示:

interface EmbeddedResponse {
  _embedded: {
    heroes: Hero[]
  }
}

The response from the server looks like this:来自服务器的响应如下所示:

{
  "_embedded" : {
    "heroes" : [ {
      "id" : 1,
      "name" : "Dicke Berta",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/heroes/1"
        },
        "hero" : {
          "href" : "http://localhost:8080/heroes/1"
        }
      }
    }, {
      "id" : 5,
      "name" : "Cobra-Car",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/heroes/5"
        },
        "hero" : {
          "href" : "http://localhost:8080/heroes/5"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/heroes"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/heroes"
    },
    "search" : {
      "href" : "http://localhost:8080/heroes/search"
    }
  }
}

The return type you defined in get is only assigned to the get function itself, not the whole chain.您在 get 中定义的返回类型仅分配给 get 函数本身,而不是整个链。 You defined get to return type Hero[], but in map you expect it to be of type EmbeddedResponse.您定义了 get 返回类型 Hero[],但在地图中您希望它是 EmbeddedResponse 类型。 Instead define get to return EmbeddedResponse:而是定义 get 以返回 EmbeddedResponse:

this.http.get<EmbeddedResponse>(this.heroesUrl)

Then you don´t even need to define the type for "res" in map, since that is then already defined (though you can also leave it for readability):然后你甚至不需要在地图中定义“res”的类型,因为它已经定义了(尽管你也可以保留它以提高可读性):

map((res) => res._embedded.heroes)

The return type of your chain is defined by the last element return something, in your case map.您的链的返回类型由最后一个元素返回的内容定义,在您的案例地图中。 res._embedded.heroes is of type Hero[], therefore your const heroes will be of type Observable<Hero[]>. res._embedded.heroes 是 Hero[] 类型,因此你的 const 英雄将是 Observable<Hero[]> 类型。

Finally in tap and catchError you probably set your brackets wrong.最后,在 tap 和 catchError 中,您可能将括号设置错了。 catchError shouldn´t be a part of tap but rather chained after it: catchError 不应该是 tap 的一部分,而是应该在它之后链接:

   tap(data => this.log('HeroService: fetched Heroes')),
   catchError(this.handleError('getHeroes', []))
);

Your catchError operator should be inside pipe not inside tap您的catchError运算符应该在管道内而不是在tap

pipe(
    map((res: EmbeddedResponse) => res._embedded.heroes),
    tap(data => this.log('HeroService: fetched Heroes')),
    catchError(this.handleError<Hero[]>('getHeroes', []))
))

Demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM