Type “json” | undefined not satisfied by “json” in Angular HttpClient

自古美人都是妖i 提交于 2020-07-09 07:19:33

问题


I'm scrutinizing the docs for HttpClient, focusing on the get(...) method. I've prepared the following sample:

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)

I get an error stating the following.

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

It's pretty obvious what's the reported issue. However, I don't see how what I typed is in validation towards what is required. If I type undefined as the value for responseType, the compiler is satisfied. In fact, the elaborated code samples (number 7, 8 and 12 through 15) explicitly state that it's the syntax to be used.

How is my "json" not the required "json"?


回答1:


The HttpClient methods use string literal types for some of the options - rather than just declaring e.g. responseType as the generic string they provide the specific values it can take. So why does your options object not meet the type definition, given it has one of the accepted values?

The initial declaration:

const responseType = "json";

defines responseType as the string literal type "json"; it's a const, it can only ever have that single value. So far, so good. However, the object declaration:

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

gives options the type { responseType: string }, it widens the type of the attribute. It does this because objects are mutable, so you could change the value.

To fix this, you have several options; in no particular order:

  • Inline the object creation:

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

    This doesn't widen the type, because you can't assign a different value into an object you don't hold a reference to.

  • Explicitly type the intermediate object:

     const options: { responseType: "json" } = { ... };
    
  • Use a const assertion on the object:

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

    This tells the compiler you aren't going to change the values and gives options the type { readonly responseType: "json" }.

  • Use a const assertion on the string (suggested by Michael D):

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

    This one's a bit weird, because the type of responseType is still "json", as it was originally. However this creates a "const context" in which that type is non-widening, so the resulting type of options is { responseType: "json" } (not readonly as above, but you can only assign that one value to it).

Here is a playground showing the various options for options: TypeScript Playground.



来源:https://stackoverflow.com/questions/62651724/type-json-undefined-not-satisfied-by-json-in-angular-httpclient

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!