web-dev-qa-db-ja.com

Angular 4/5 HttpClient:文字列型の引数は 'body'に割り当てられません

Angularドキュメントには次のように書かれています:

応答本文は、必要なすべてのデータを返しません。サーバーは特定の条件を示すために特別なヘッダーまたはステータスコードを返すことがあり、それらの検査が必要になる場合があります。これを行うには、observオプションを使用して、本文だけでなく完全な応答が必要であることをHttpClientに伝えることができます。

http
  .get<MyJsonData>('/data.json', {observe: 'response'})
  .subscribe(resp => {
    // Here, resp is of type HttpResponse<MyJsonData>.
    // You can inspect its headers:
    console.log(resp.headers.get('X-Custom-Header'));
    // And access the body directly, which is typed as MyJsonData as requested.
    console.log(resp.body.someField);
  });

しかし、それを試みると、コンパイル時エラーが発生します(ただし、ランタイムエラーは発生せず、期待どおりに動作します)。

エラーTS2345:型 '{headers:HttpHeaders;の引数。観察する:文字列; } 'は、タイプ' {headers ?: HttpHeaders | {[ヘッダー:文字列]:文字列| string []; };観察しますか?: "body"; params ?: Ht ... '。プロパティ「observe」のタイプには互換性がありません。タイプ 'string'は、タイプ '"body"'に割り当てることができません。

どうして? "@angular/http": "^5.1.0"を使用します

コードのバージョンは次のとおりです。

  login(credentials: Credentials): Observable<any> {
    const options = {
      headers: new HttpHeaders({'Content-Type': 'application/json'}),
      observe: 'response'
    };
    return this.httpClient.post<any>(`${environment.USER_SERVICE_BASE_URL}`,
      {'username': credentials.username, 'password': credentials.password}, options)
      .map((res) => ...
15
Phil

オプションをインライン化する必要があります。 github ticket#18586 、2017年8月9日のalxhubによるエントリを参照してください。

TypeScriptは、get()の正しい戻り値の型を選択するために、observeおよびresponseTypeの値を静的に推測できる必要があります。不適切に型指定されたオプションオブジェクトを渡すと、正しい戻り値の型を推測できません。

login(credentials: Credentials): Observable<any> {
    return this.httpClient.post<any>(`${environment.USER_SERVICE_BASE_URL}`,
      {'username': credentials.username, 'password': credentials.password}, {
      headers: new HttpHeaders({'Content-Type': 'application/json'}),
      observe: 'response'
    })
      .map((res) => ...
31
Igor

TypeScriptはこの問題について不平を言っています

タイプ「string」はタイプ「body」に割り当てられません

これを解決するには、文字列を手動でボディに変換します。例:

    const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json'
      }),
      observe: 'response' as 'body'
    };
    return this.http.post<any>(url, data, httpOptions);

オプションをインライン化せずにこれを回避する方法(コードはそれほどきれいではない可能性があります)は、要求オプションのインターフェイスを作成することでした。コードは次のようになります。

export interface IRequestOptions {
    body?: any;
    headers?: HttpHeaders | { [header: string]: string | Array<string> };
    observe?: any;
    params?: HttpParams | { [param: string]: string | Array<string> };
    reportProgress?: boolean;
    responseType?: "arraybuffer" | "blob" | "json" | "text";
    withCredentials?: boolean;
}

次に、これがそのように使用されます:

const options: IRequestOptions = {
    headers: new HttpHeaders({"Content-Type": "application/json"}),
    observe: "response"
};
return this.httpClient.post(`${environment.USER_SERVICE_BASE_URL}`,
    {"username": credentials.username, "password": credentials.password}, options)
    .pipe(
        map((res: HttpResponse<any>) => ...
    );

元の投稿がlettableまたはpipeable(現在の名前が何であれ)演算子を使用するように変更

9
blo0p3r