了解复杂的类型脚本类型声明

时间:2019-04-18 13:36:16

标签: angular typescript httpclient

问题是关于如何使用对象类型发送标头(HTTPClient声明中提供的HttpHeaders除外)。

当使用Angular HttpClient时,我想将标头传递给Object,我不明白如何定义 [header:string]:string |类型的对象。 string []; ,请帮助我理解此对象声明。同样,我也面临着HttpParams的问题。我的代码方法如下。

getLoggedInUser(requestHeaderParam: GetLoggedInUserHeaderRequestParam): Observable<LoggedInUserResponse> {
   return this.http.get<LoggedInUserResponse>(`${environment.apiBaseUrl}/auth/loggedInUser`,
    { headers: requestHeaderParam }); 
}

我在VS代码中收到如下错误消息

  

[ts]类型为'{头的参数:GetLoggedInUserHeaderRequestParam;   }'不可分配给类型'{headers ?: HttpHeaders | {   [标题:字符串]:字符串|串[]; };观察?参数?:   H T...'。属性“标题”的类型不兼容。       类型'GetLoggedInUserHeaderRequestParam'不能分配给类型'HttpHeaders | {[header:string]:字符串|串[]; }'。         类型'GetLoggedInUserHeaderRequestParam'不可分配给类型'{[标头:字符串]:字符串|串[]; }'。           类型'GetLoggedInUserHeaderRequestParam'中缺少索引签名。

请求参数类型如下

export interface GetLoggedInUserHeaderRequestParam {
  uid: string;
  PSID?: string;
}

如下所示的HttpClient声明。

HttpClient.get(url: string, options: {
   headers?: HttpHeaders | {
    [header: string]: string | string[];
   };
   observe?: "body";
  params?: HttpParams | {
    [param: string]: string | string[];
  };
  reportProgress?: boolean;
  responseType: "arraybuffer";
  withCredentials?: boolean;
}): Observable<ArrayBuffer>

请帮助!!!

注意我的问题不是如何使用HttpHeaders,我得到了如何使用HttpHeaders,我的问题是如何如其声明类型之一所述直接使用Object { [标题:字符串]:字符串|串[]; }在HttpClient中

3 个答案:

答案 0 :(得分:3)

问题是GetLoggedInUserHeaderRequestParam和标头直接对象的签名

例如

  export interface GetLoggedInUserHeaderRequestParam {
      uid: string;
      PSID?: string;
    }

仅接受带有uid和可选PSID的wherease标头直接对象的对象

   {
      [header: string]: string | string[];
   }

说它可以接受带有任意多个类型为string和value的键的对象作为字符串或字符串数​​组。

键的区别是您的界面强制Typescript接受具有确切键名的对象,而标头对象可以接受任何类型的字符串,如

{
  "uid" : "1234",
  "PSID" : "1223",
  "name" : "test",
  ..... 
}

您可以通过将接口定义为

来解决问题
interface GetLoggedInUserHeaderRequestParam {
    [name: string] : string | string[];

}

并以

调用HTTP方法
let header: GetLoggedInUserHeaderRequestParam  = {
  "uid" : "1234",
  "PSID" : "1234"
}

getLoggedInUser(header);

答案 1 :(得分:2)

应该是这样的:

headers是HTTP头。您提供的是数据

getLoggedInUser(requestHeaderParam: GetLoggedInUserHeaderRequestParam): Observable<LoggedInUserResponse> {

     let headers = new HttpHeaders();
     headers = headers.set('Content-Type', 'application/json');

   return this.http.get<LoggedInUserResponse>(`${environment.apiBaseUrl}/auth/loggedInUser`, JSON.stringify(requestHeaderParam),
    { headers: headers }); 
}

对于参数:

    import {HttpParams} from "@angular/common/http";

getLoggedInUser(requestHeaderParam: GetLoggedInUserHeaderRequestParam): Observable<LoggedInUserResponse> {

    const params = new HttpParams()
        .set('uid', requestHeaderParam.uid)
        .set('PSID', requestHeaderParam.PSID);

     return this.http.get<LoggedInUserResponse>(`${environment.apiBaseUrl}/auth/loggedInUser`, 
        {params:params}); 
}

答案 2 :(得分:2)

您正试图将符合GetLoggedInUserHeaderRequestParam的对象作为headersparams传递给HttpClient.get的{​​{1}},但这不是安全类型,那就是为什么TypeScript阻止您执行此操作。

请参见,您声明参数options。这表示requestHeaderParam: GetLoggedInUserHeaderRequestParam

  1. 必须具有一个requestHeaderParam的{​​{1}}字段。
  2. 可能有一个uid的{​​{1}}字段。

但是它没有说明任何其他字段。一个对象可以满足该界面并包含其他字段。并且其中一些其他字段可能不是string。这是一个例子。为了说明我在说什么,我摘录了部分代码,并删除了一些不重要的内容:

PSID

我已经给出了两个调用string的示例,第一个可以很好地编译。第二个没有。第二个示例可能使TypeScript的一些用户认为,如果在接口上未定义字段,则不允许使用该字段,但通常情况并非如此。当TypeScript将接口应用于对象文字时,它将拒绝接口中未定义的那些字段,但是此行为仅适用于对象文字。 (并且可以使用类型断言来覆盖它。)上面显示的对string的第一次调用向您展示了在一般情况下发生的情况:一个对象可以满足一个接口,但是具有其他字段。

那为什么会有问题呢? interface GetLoggedInUserHeaderRequestParam { uid: string; PSID?: string; } function getLoggedInUser(requestHeaderParam: GetLoggedInUserHeaderRequestParam): void { } const params = { uid: "1", rogue: getLoggedInUser, // Let's pass a function! }; // This compiles just fine despite params having an extra field. getLoggedInUser(params); // This does not compile. getLoggedInUser({ uid: "1", rogue: getLoggedInUser, // Let's pass a function! }) 的{​​{1}}声明告诉您getLoggedInUser想要一个对象,其键为字符串,其值为字符串或字符串数​​组。 值不能是任何其他类型。我们已经看到,不能保证getLoggedInUser不会包含违反此要求的字段。它会有一个{ [header: string]: string | string[] }字段,它是一个字符串,它可能有一个headers字段,如果有的话,它是一个字符串,但是 可能还有其他字段不是字符串或字符串数​​组。因此,编译器正确地引发了一个错误。如果您尝试使用HttpClient.get,则适用相同的逻辑。

所需的解决方案主要取决于使用代码的上下文。最小的解决方案是简单地执行类型断言:

requestHeaderParam

您必须首先通过uid(或PSID)进行转换,因为类型是完全不兼容的。 请注意,如果仅使用类型断言,那么如果传递的值不是paramsthis.http.get(..., { headers: requestHeaderParam as unknown as Record<string, string>}) ,则不会受到保护。数据只会传递到{{ 1}},您将收到错误或未定义的行为。

或者您可以在测试对象没有任何其他字段之后执行类型断言

或者将unknown设为特定类的对象 可能更有意义,其中a)强制设置可以设置的字段,b)具有返回纯JS的方法符合any要求的对象。