【问题标题】:angular Property 'value' does not exist on type 'Object'“对象”类型上不存在角度属性“值”
【发布时间】:2021-04-11 07:17:22
【问题描述】:

在我的 Angular 应用程序中,API 调用的响应存在问题:

 private async getActor(actor:string) {
    const response = await this.searchActor.getActorImage(actor).toPromise()
    let actPics = []    
      for (var val of (response as any[]).value) {
        actPics.push(val.thumbnailUrl)}                   
  }

我的应用程序运行良好,但是当我运行 ng serve 时控制台中出现此消息

错误: src/app/quiz-editor/actor-question/actor-question.component.ts:55:41 - 错误 TS2551:类型“任何 []”上不存在属性“值”。你是否 意思是“价值观”?

55 for (var val of (response as any[]).value) { ~~~~~

node_modules/typescript/lib/lib.es2015.iterable.d.ts:75:5 75 个值():可迭代迭代器; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'values' 在这里声明。

当我console.log(response) 我得到:

我做了一些研究,读到我应该声明response,但我应该怎么做呢?

我试过这个解决方案:

private async getActor(actor:string) {
    const response: { value:any[] } = await this.searchActor.getActorImage(actor).toPromise()
    let actPics = []      
    for (let val of response.value) {
      actPics.push(val.thumbnailUrl)}
}

但现在我有这个错误:

 Error: src/app/quiz-editor/actor-question/actor-question.component.ts:55:11 - error TS2696: The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?
      Property 'value' is missing in type 'Object' but required in type '{ value: any[]; }'.

55     const response: { value:any[] } = await this.searchActor.getActorImage(actor).toPromise()
             ~~~~~~~~

  src/app/quiz-editor/actor-question/actor-question.component.ts:55:23
    55     const response: { value:any[] } = await this.searchActor.getActorImage(actor).toPromise()
                             ~~~~~
    'value' is declared here.

【问题讨论】:

  • 你需要给response添加类型
  • 以同样的方式声明其他任何内容 const response: { value: any[] } = ... 或其他任何内容。见Type definition in object literal in TypeScript
  • searchActor.getActorImage 的签名是什么?它与@tilo 建议的响应类型冲突
  • 这似乎不正确for (var val of (response as any[]).value) 。 Array 类型没有value 属性,你确定这里没有弄错吗
  • for (var val of (response as any[]).value) {这一行改为for (var val of (response as any).value) {

标签: angular typescript


【解决方案1】:

你只需要改变类型

const response:{value:any[]}

const response:any

两者都可以

【讨论】:

    【解决方案2】:

    错误是由于您将响应投射到“any[]”这一事实造成的。 => 你有两个解决方案:

    1. 你删除了铸件(没有必要):

      私有异步 getActor(actor:string) { const {value} = 等待 this.searchActor.getActorImage(actor).toPromise() const actPics = value.map(val => val.thumbnailUrl)
      }

    2. 您声明了一个表示您的 API 响应类型的接口

    【讨论】:

      【解决方案3】:

      您错误地尝试将response 定义为一个数组。 Javascript Array 显然没有 value 属性或方法。您需要改为定义以下接口。

      export interface IResponse {
        currentOffset: number;
        instrumentation: any;
        nextOffset: number;
        queryContext: any;
        readLink: string;
        totalEstimatedMatches: any;
        value: Array<any>;
        webSearchUrl: string;
        _type: string;
      }
      

      在理想情况下,您还可以为instrumentationqueryContexttotalEstimatedMatches 以及value 数组中包含的对象定义类似的接口,并使用它们而不是使用any

      此外,您不需要显式循环来从对象中获取值数组。您可以改用Array#map 方法。

      export interface IResponse {
        currentOffset: number;
        instrumentation: any;
        nextOffset: number;
        queryContext: any;
        readLink: string;
        totalEstimatedMatches: any;
        value: Array<any>;
        webSearchUrl: string;
        _type: string;
      }
      
      @Component({...})
      export class SomeComponent implements OnInit, OnDestroy {
        private async getActor(actor:string) {
          const response: IResponse = await this.searchActor.getActorImage(actor).toPromise();
          let actPics: Array<string> = response.value.map(val => val['thumbnailUrl']);
        }
      }
      

      补充说明:

      1. 尝试使用 RxJS observable 而不将其转换为 Promise。 Observables 在 Promises 上提供了一系列 advantages

      2. toPromise() 方法在 RxJS 7 中将是 deprecated 并且将在 RxJS 8 中消失。

      【讨论】:

        【解决方案4】:

        您将response 声明为any 类型的数组,这是不正确的。 response 不是数组,response.value 是数组。 any 关键字告诉 typescript 不要打扰类型检查。来自the docs

        在某些情况下,并非所有类型信息都可用,或者其声明会花费不适当的努力。这些可能发生在没有 TypeScript 或 3rd 方库的情况下编写的代码中的值。在这些情况下,我们可能希望选择退出类型检查。为此,我们将这些值标记为 any 类型

        因此,快速而肮脏的解决方法是告诉 typescript responseany 类型,这样做:

         private async getActor(actor:string) {
            const response = await this.searchActor.getActorImage(actor).toPromise()
            let actPics = []    
              for (var val of (response as any).value) {
                actPics.push(val.thumbnailUrl)}                   
          }
        

        另一种可能更适合 Angular 的做事方式是创建一个模型并将其用作您的类型。这是一个精简的模型:

        export class ImageSearchResult {
            // you could/should type this as well instead of being an array of 
            // type any. It might be something like value: []ImageData;
            value: []any; 
        }
        

        然后,您使用您的模型类型而不是任何类型:

         private async getActor(actor:string) {
            const response = await this.searchActor.getActorImage(actor).toPromise()
            let actPics = []    
              for (var val of (response as ImageSearchResult).value) {
                actPics.push(val.thumbnailUrl)}                   
          }
        

        但更进一步,您的服务应该返回正确的类型。输入服务返回的数据不是使用服务的模块的工作。另外-我假设您要返回observable。为什么打电话给toPromise?让我们创建一个使用 Angular 的 http 服务并返回正确类型的 observable 的服务函数。你可能已经有了这样的东西:

          import { HttpClient } from '@angular/common/http';
          
          constructor(private http: HttpClient) { }
        
          /**
           * Search for images by actor. Returns an observable of type ImageSearchResult.
           * @param actor The name of the actor you want to search
           */
          getActorImage(actor: string): Observable<ImageSearchResult> {
            // Refactor to appropriate http action type (post/push/etc) and url.
            return this.http.get<ImageSearchResult>(`https://my-api.com/actor-search?q=${actor}`);
          }
        

        然后消费这个服务函数:

        private getActor(actor:string) {
          this.searchActor.getActorImage(actor).subscribe(response => {
            let actPics = []
            // No casing necessary, response is already correct type.
            for (var val of response.value) {
              actPics.push(val.thumbnailUrl)
            }
          });
        }
        

        最后,您似乎在尝试使用 Azure 图像搜索 API。在这种情况下,请查看how they type the return objects for inspiration。根据您项目的许可证,您可能只需导入该项目并将其模型与您的服务一起使用。

        【讨论】:

          【解决方案5】:

          你必须告诉 typescript 你的数组是什么类型。通过说response as any[],编译器不知道您的数组包含哪些对象。它可能在运行时工作,因为打字稿然后“找到”请求的属性。 因此,您应该做的是创建一个类/接口来定义您希望从 API 接收的对象,然后解析对它的响应。

          例子:

          private async getActor(actor:string) {
          const response = await this.searchActor.getActorImage(actor).toPromise();
          const images = response as actorImage[];
          let actPics = [];    
            for (var val of images) {
              actPics.push(val.thumbnailUrl)}                   
          

          }

          interface actorImage{
            thumbnailUrl: string   
          }
          

          【讨论】:

            【解决方案6】:

            正如您的日志语句所示,您的 response 是一个包含 value 作为键的对象。因此,您可以执行以下操作:

            const response: { value: any[] } = await this.searchActor.getActorImage(actor).toPromise();
            let actPics = [];
            for (let val of response.value) {
              actPics.push(val.thumbnailUrl);                   
            }
            

            【讨论】:

            • 好吧,您可以在服务中添加一个类型(例如,this.http.get&lt;any&gt;('__url__')),或者使用括号表示法(response['value'] + 删除响应声明)来解决这个问题
            猜你喜欢
            • 1970-01-01
            • 2020-07-07
            • 2018-01-09
            • 2021-08-22
            • 2021-07-31
            • 1970-01-01
            • 2018-09-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多