Angular 4/5 HttpClient: Аргумент типа string нельзя назначить для body

В угловых документах сказано:

Тело ответа не возвращает все данные, которые вам могут понадобиться. Иногда серверы возвращают специальные заголовки или коды состояния, чтобы указать определенные условия, и проверка их может быть необходимой. Чтобы сделать это, вы можете указать 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 | { [header: string]: строка | Строка []; }; наблюдать?: "тело"; params?: Ht...'. Типы собственности "наблюдать" несовместимы. Тип '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) => ...

2 ответа

Решение

Вы должны указать параметры. Смотрите GitHub билет № 18586, вход по alxhub 9 августа 2017 г.

Typescript должен иметь возможность выводить значения наблюдаемого и responseType статически, чтобы выбрать правильный тип возвращаемого значения для get(). Если вы передадите неправильно заданный объект параметров, он не сможет определить правильный тип возвращаемого значения.

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) => ...

Машинопись жалуется на эту проблему

Тип '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 (каким бы ни было текущее имя сегодня) операторы

import { HttpHeaders, HttpParams } from '@angular/common/http';
export interface IRequestOptions {
    headers?: HttpHeaders | { [header: string]: string | string[]; };
    observe: "response"; 
    params?: HttpParams | { [param: string]: string | string[]; };
    reportProgress?: boolean; 
    responseType?: "json";
    withCredentials?: boolean; 
}
Другие вопросы по тегам