【问题标题】:can't build angular app due to httpClient response data array throwing typescript build issue由于 httpClient 响应数据数组引发 typescript 构建问题,无法构建 Angular 应用程序
【发布时间】:2019-09-23 21:48:36
【问题描述】:

您好几年没玩编码游戏了,我正在加速使用 Angular 8(不喜欢它!)我可以运行 ng serve 并且一切正常,但如果我尝试构建,我会在这里遇到错误

userD() {
  // TODO User Angular Service will get to that later.
  var aToken = localStorage.getItem('token');
  const headers = new HttpHeaders().set("Authorization", "Bearer " + aToken);

  this.httpClient.get( 'http://127.0.0.1:8000/api/auth/user', { headers } )
  .subscribe((res: any[]) => {
    // @ts-ignore
    this.users = res.data.result; // it doesn't like the .data.result part in build
    console.log(this.users);
  });
}

我现在正在使用 //@ts-ignore,并不理想,但我不知道为什么它在进入数组时会出现问题,如果我将它作为 res 就可以了。

任何信息都会非常有助于帮助我理解这一点。谢谢。

注意:编辑 这是json 我想提取到这个结果对象,然后在 html 中使用 For 循环 {"status":"200", "data": {"result":{"id":3,"name":"patrick lord","email":"patrick@larvel.io","email_verified_at": null,"电话":"123456789","profilePic":71,"created_at":"2019-09-19 19:43:04","updated_at":"2019-09-19 19:43:04", "stripe_id":null,"card_brand":null,"card_last_four":null,"trial_ends_at":null,"gender":"male","Address1":"我不住在这里 S","Address2": "232","City":"Clearfield","Country":"USA","Zip_Post":"55550","YouTube"}}}

【问题讨论】:

  • 为什么数组 (res: any[]) 会有 data 属性?
  • 嘿 JB 感谢您回复数据在响应中不是属性

标签: angular typescript httpclient build-error


【解决方案1】:

解释

JB 的 comment 正中要害:您遇到了 TypeScript 错误,因为 any[] 类型没有 data 属性;根据定义,any[] 期待 anything,唯一的限制是输入必须是 Array 类型的对象。

但是为什么build --prod 中的错误而不是serve 中的错误?

您在ng build --prod 上收到错误,而在ng serve 上出现not 是因为默认 Angular 环境在 @ 上强制执行 strict(如“严格遵守键入和语法”) 987654332@,但在本地开发环境中强制执行strict。这样一来,在清理代码以供生产使用之前,您可以在本地开发时更轻松地解决问题,其中草率的语法不是问题。我也花了一点时间来解决这个问题,但这是一件好事(tm):P

理由

JavaScript 可以让你做任何你想做的事:它不知道res 会是什么样子,但它假设你知道你在做什么,如果你说res 将有一个属性称为data,它只是随它滚动。

如果您有一个小项目,或者如果您是唯一人会一直从事该项目,那就太好了,但是当项目变得更大时,它开始变得棘手,或者如果您有多个开发人员提交代码。 知道res有一个data属性,但是Samantha怎么知道呢?

输入TypeScript

TypeScript 是 JavaScript...带有类型。类型提供给定对象的 shape,因此所有相关人员(包括 TypeScript 转译器)都知道发生了什么。当你说 res: any[] 时,TS 听到的是“对象 res 将成为 Object 类型的 Array”;然而,我们还没有告诉 TS 关于数组中的成员项within 的任何信息,因为它不知道 种类 是什么数组res 将是,我们唯一可以访问的是Array 类型本身的泛型方法和属性。

修复

那么,我们需要做什么而不是 (res: any[]) 来使 this.users = res.data.result; 工作?

为 ResponseObject 定义一个接口

我们需要先告诉 TS 会发生什么,并提供更多细节:

export interface ResponseObject {
  data: {
    result: {};
  }
}

现在 TS 知道有一个名为 ResponseObjectResponseObject 具有(至少)一个 data 属性,而 data 属性本身是一个具有 (再次,至少)一个名为result的属性。

告诉 TypeScript 期待我们的 ResponseObject

我们可以像这样将它插入到我们的订阅调用中:

.subscribe( (res: ResponseObject) => {
  this.users = res.data.result; // now it totally DOES like the .data.result part in build --prod!
  console.log(this.users);
});

等一下……

您可能注意到res 不再是Array 类型的对象;根据您发布的代码以及您说它通过ng serve 工作的事实,听起来您期待一个响应对象,它提供一组用户对象作为data.result 属性上的有效负载;如果是这样,上面的代码示例应该可以正常工作。

但是,如果我们的.get() 真的返回一个数组 ResponseObjects,我们将需要做一些额外的工作。

处理 ResponseObjects 数组

让我们先修改一下接口声明:

export interface ResponseObject {
  status: number;  /*  It's OK to exclude things we don't need,
      but, the status property is going to come in handy when
      we eventually want to write a catch statement for cases
      when the call returns an error instead of the data we
      wanted  */
  data: {
    /*  you can also split up your interface declarations to
        make them easier to read; this has the added benefit of
        allowing us to more easily access the sub-properties of
        our payload later on  */
    result: UserObject;  /*  we're expecting a single
        UserObject per ResponseObject in this scenario,
        otherwise we'd use:  */
    // result: UserObject[];
  }
}

export interface UserObject {
  /*  remember to use the generic type names (lowercase 'string'),
      not Primitives (Capitalized 'String') in your interface
      declaration, otherwise you'll get more errors  */
  id: number;
  name: string;
  email?: string;  /*  the question mark lets you define a
    property that *may* exist, but may not.  Useful if your
    target API only includes parameters with non-null values
    in the ResponseObject   */
  // ...all the other things you want and think will exist
}

然后我们可以混合订阅调用:

.subscribe(
  // we tell subscribe that we're expecting an array of ResponseObjects
  (res: ResponseObject[]) => {
    /*  users needs to be defined as an array to hold onto
        multiple UserObjects; we're clearing it here to make
        sure we're only dealing with fresh data and specifying
        that it will be an array of type UserObject  */
    this.users: UserObject = [];

    /*  the data property isn't a property of the *array*, but
        of each array *member-item*, so we need a loop  */
    res.forEach(
      (res_item: ResponseObject) => {
        // add the response object data to our users array
        this.users.push(res_item.data.result);
    });

    // now console log should properly show our array of UserObjects!
    console.log(this.users);
  }
);

n.b., 如果它确实令人满意地回答了您的问题,请不要忘记将其标记为已接受的答案。如果有人对您的问题提出了更好或更简洁的答案,您可以随时更改已接受的答案。

干杯!

【讨论】:

  • 所以是的,我的回应是因为我返回的 json 具有这种结构,对不起,我很着急,应该包括这个。 {"status":"200", "data": {"result":{"id":3,"name":"patrick lord","email":"patrick@larvel.io","email_verified_at": null,"电话":"123456789","profilePic":71,"created_at":"2019-09-19 19:43:04","updated_at":"2019-09-19 19:43:04", "stripe_id":null,"card_brand":null,"card_last_four":null,"trial_ends_at":null,"gender":"male","我不住在这里 S","Address2":"23223", "City":"Clearfield","Country":"USA","Zip_Post":"99898","YouTube"}}}
  • 这是一个了不起的答案!你已经分解了我的问题并解释了答案。我希望以这种方式完成更多的答案。非常感谢您花时间整理这个答案。 “萨曼莎”将感谢 HA
  • 很高兴听到它有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
相关资源
最近更新 更多