繁体   English   中英

angular 属性“值”在“对象”类型上不存在

[英]angular Property 'value' does not exist on type 'Object'

在我的 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:“任何 []”类型上不存在属性“值”。 您指的是 'values' 吗?

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

node_modules/typescript/lib/lib.es2015.iterable.d.ts:75:5 75 个值():IterableIterator; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 这里声明了“值”。

当我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是一个包含value作为键的 object。 因此,您可以执行以下操作:

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

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

例子:

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   
}

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

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

因此,快速而肮脏的解决方法是告诉 typescript response类型为any ,执行如下操作:

 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 的做事方式是创建 model 并将其用作您的类型。 这是一个精简的 model:

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; 
}

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

 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 让我们创建一个服务 function,它使用 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}`);
  }

然后消费这个服务function:

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。 在这种情况下,看看他们如何键入返回对象以获得灵感 根据您项目的许可证,您可能只需导入该项目并将其模型与您的服务一起使用。

您错误地尝试将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数组中的 object 定义类似的接口,并使用它们而不是使用any

此外,您不需要显式循环来从 object 获取值数组。 您可以改用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 而不将其转换为 Promise。 Observables 提供了一系列优于 Promises 的优势

  2. toPromise()方法将在 RxJS 7 中弃用,并将在 RxJS 8 中消失。

该错误是由于您将响应投射到“any []”而引起的。 => 你有 2 个解决方案:

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

    private async getActor(actor:string) { const {value} = await this.searchActor.getActorImage(actor).toPromise() const actPics = value.map(val => val.thumbnailUrl)
    }

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

你只需要改变类型

const response:{value:any[]}

或者

const response:any

两者都可以

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM