将 http 选项设置为 'responseType: 'text'' 会导致使用 angular HttpClient 的 http post 请求编译失败

Setting http option as 'responseType: 'text'' causes compile failure for a http post request with angular HttpClient

尽管在 angular HttpClient 中有一个重载的 API 方法,如下所示:

 post(url: string, body: any | null, options: {
        headers?: HttpHeaders | {
            [header: string]: string | string[];
        };
        observe?: 'body';
        params?: HttpParams | {
            [param: string]: string | string[];
        };
        reportProgress?: boolean;
        responseType: 'text';
        withCredentials?: boolean;
    }): Observable<string>;

当我尝试使用选项 'responseType: 'text'' 执行以下 post 请求时,我收到一个编译器错误,指出 "No overload matches this call. ..."

const opts = {
      headers: new HttpHeaders({
        'Accept': 'text/html, application/xhtml+xml, */*',
        'Content-Type': 'text/plain; charset=utf-8'
      }),
      responseType: 'text'
    };
    return this.http.post<string>('url', null, opts);

注意:我明智地将 null 作为响应主体传递,因为我的 API 不接受主体。 我在这里做什么可能是错误的?

更新 根据 Michael D

的要求添加完整的错误消息
Type 'Observable<ArrayBuffer>' is not assignable to type 'Observable<string>'.
  Type 'ArrayBuffer' is not assignable to type 'string'.ts(2322)
No overload matches this call.
  Overload 1 of 15, '(url: string, body: any, options: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe: "events"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }): Observable<...>', gave the following error.
    Argument of type '{ headers: HttpHeaders; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe: "events"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }'.
      Property 'observe' is missing in type '{ headers: HttpHeaders; responseType: string; }' but required in type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe: "events"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }'.
  Overload 2 of 15, '(url: string, body: any, options: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe: "response"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }): Observable<...>', gave the following error.
    Argument of type '{ headers: HttpHeaders; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe: "response"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }'.
      Property 'observe' is missing in type '{ headers: HttpHeaders; responseType: string; }' but required in type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe: "response"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }'.
  Overload 3 of 15, '(url: string, body: any, options?: { headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }): Observable<...>', gave the following error.
    Argument of type '{ headers: HttpHeaders; responseType: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: HttpParams | { [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: "json"; withCredentials?: boolean; }'.
      Types of property 'responseType' are incompatible.
        Type 'string' is not assignable to type '"json"'.ts(2769)
http.d.ts(2293, 9): 'observe' is declared here.
http.d.ts(2409, 9): 'observe' is declared here.

问题出在 responseType 属性 上。像这样将其分配为字符串不会立即起作用。

您可以将其转换为 text 类型

const opts  = {
  headers: new HttpHeaders({
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Content-Type': 'text/plain; charset=utf-8'
  }),
  responseType: 'text' as 'text' //<== here
};

    this.http.post(....);

编辑 这仅适用于使用非通用版本的 http 调用(this.http.post(...) 但不适用于通用版本 this.http.post<string>

或者,您可以将选项声明为 any,这应该会阻止编译器报错

const opts : any = {
  headers: new HttpHeaders({
    'Accept': 'text/html, application/xhtml+xml, */*',
    'Content-Type': 'text/plain; charset=utf-8'
  }),
  responseType: 'text'
};

this.http.post<string>(....)

虽然这是奇怪的行为。 HttpClient 中的 options 实际上不是任何类型。它是为每个重载定制的。

您必须将 options 作为一个整体传递到 http 调用中。

return this.http.post<string>('url', null, {
      headers: new HttpHeaders({
        'Accept': 'text/html, application/xhtml+xml, */*',
        'Content-Type': 'text/plain; charset=utf-8'
      }),
      responseType: 'text'
    });

或者按照 David 的建议将 options 类型设置为 any

opts['responseType'] 被推断为 string。尝试 responseType: 'text' as const

const opts = {
   ...
} as const;

感谢回复者的评论,我想我已经找出代码中的错误 here 问题是我正在尝试对 post() 方法调用使用泛型类型,它仅在 responseType 等于 'json' 时适用。看看下面 HttpClient 的 post 方法重载声明

post(url: string, body: any | null, options: {
        headers?: HttpHeaders | {
            [header: string]: string | string[];
        };
        observe?: 'body';
        params?: HttpParams | {
            [param: string]: string | string[];
        };
        reportProgress?: boolean;
        responseType: 'text';
        withCredentials?: boolean;
    }): Observable<string>;

 post<T>(url: string, body: any | null, options?: {
        headers?: HttpHeaders | {
            [header: string]: string | string[];
        };
        observe?: 'body';
        params?: HttpParams | {
            [param: string]: string | string[];
        };
        reportProgress?: boolean;
        responseType?: 'json';
        withCredentials?: boolean;
    }): Observable<T>;

因此下面是我的问题的工作代码

 apiMethod(): Observable<string> {

    const options  = {
      headers: new HttpHeaders({
        'Accept': 'text/html, application/xhtml+xml, */*',
        'Content-Type': 'text/plain; charset=utf-8'
      }),
      responseType: 'text' as 'text'
  };
    return this.http.post('url', null, options);
  }