输入 "json" | Angular HttpClient 中的 "json" 不满足 undefined

Type "json" | undefined not satisfied by "json" in Angular HttpClient

我正在仔细检查 docs for HttpClient, focusing on the get(...) 方法。我准备了以下示例:

const headers: HttpHeaders = new HttpHeaders();
const observe: HttpObserve = null;
const params: HttpParams = new HttpParams();
const reportProgress = false;
const responseType = "json";
const withCredentials = true;

const options = {
  headers, observe, params,
  reportProgress, responseType, withCredentials
};

this.http.get(url, options)

我收到一条错误消息,说明如下。

No overload matches this call.  
The last overload gave the following error.  
Argument of type '{ responseType: string; ... }'  
is not assignable to parameter of type '{ responseType?: "json" | undefined; ... }'.  
Types of property 'responseType' are incompatible.
Type 'string' is not assignable to type '"json" | undefined'.

很明显报告的问题是什么。但是,我没有看到 我输入的内容 如何验证 需要的内容。如果我键入 undefined 作为 responseType 的值,编译器会满意。事实上,详尽的代码示例(编号 7、8 和 12 到 15)明确说明它是要使用的语法。

我的"json"怎么不是要求的"json"

HttpClient 方法对某些选项使用 string literal types - 而不仅仅是声明,例如responseType 作为通用 string 它们提供了它可以采用的特定 。那么为什么你的options对象满足类型定义,因为它具有可接受的值之一?

初始声明:

const responseType = "json";

定义responseType为字符串文字类型"json";它是一个 const,它只能有一个值。到目前为止,一切都很好。但是,object 声明:

const options = { responseType /* etc. */ };

赋予options类型{ responseType: string },它扩展属性的类型。它这样做是因为对象 可变 ,因此您可以更改值。

要解决此问题,您有多种选择;排名不分先后:

  • 内联对象创建:

     this.http.get(url, { responseType });
    

    这不会扩大类型,因为您不能将不同的值分配给您没有引用的对象。

  • 显式键入中间对象:

     const options: { responseType: "json" } = { ... };
    
  • 对象上使用const assertion:

     const options = { responseType } as const;  // or = <const>{...};
    

    这告诉编译器您不打算更改值并为 options 提供类型 { readonly responseType: "json" }

  • 字符串使用const断言(建议):

    const responseType = "json" as const;  // or = <const>"json";
    

    这个有点奇怪,因为 responseType 的类型仍然是 "json",因为它是原来的。然而,这会创建一个 "const context",其中该类型是 non-widening,因此结果类型 options{ responseType: "json" }(不是上面的 readonly,但您只能为其分配一个值)。

这里是显示 options 的各种选项的游乐场:TypeScript Playground