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

mapping http response to object array in type argument

我想知道是否有人可以向我解释这个错误,因为我对 angular、typescript 和 rxjs 比较陌生。

我尝试做的是将调用 getHeroes() 时得到的服务器响应映射为一种格式,使我的组件可以轻松使用它。

这是我的 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
  }

注意 any 类型参数 this.http.get<any>()

我想更具体地说明 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
  }

注意 Hero[] 类型参数 this.http.get<Hero[]>()

但是将 getHeroes() 中的类型参数从 any -> Hero[] 更改为此错误:

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'.

EmbeddedResponse 界面如下所示:

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

来自服务器的响应如下所示:

{
  "_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"
    }
  }
}

你在get中定义的return类型只赋值给get函数本身,而不是整个链。您定义了 get to return type Hero[],但在 map 中您希望它是 EmbeddedResponse 类型。而是将 get 定义为 return EmbeddedResponse:

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

那么你甚至不需要在地图中定义“res”的类型,因为它已经定义好了(尽管为了便于阅读你也可以保留它):

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

你的链的 return 类型由最后一个元素 return 定义,在你的案例映射中。 res._embedded.heroes 是 Hero[] 类型,因此你的 const heroes 将是 Observable 类型。

最后在 tap 和 catchError 中你可能设置了错误的括号。 catchError 不应该是 tap 的一部分,而是链接在它之后:

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

您的 catchError 运算符应该在管道内而不是在 tap

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

Demo