错误 TS2339:属性 'name' 在类型 'any[]' 上不存在

error TS2339: Property 'name' does not exist on type 'any[]'

我搜索了 Angular 文档和此处的 Whosebug,但没有任何问题看起来像我的问题。我可能有什么不明白。但我的问题如下:

Angular CLI:11.0.2 节点:14.15.1

我的服务:

export class ApiService {

  constructor(private httpClient: HttpClient) { }

  /**
   * Get teams by id
   * @param id 
   * @returns 
   */
   getTeamFromServe(id: number){
    return this.httpClient.get('https://api.football-data.org/v2/teams/'+ id, {
      headers: {
        'X-Auth-Token': 'XXXXXXXXXXXXXXXXX'
      },
      observe: 'body',
      responseType: 'text'
    })
  }
} 

在我的组件中:

团队-details.components.js :

@Component({
  selector: 'app-team-detail',
  templateUrl: './team-detail.component.html',
  styleUrls: ['./team-detail.component.scss']
})
export class TeamDetailComponent implements OnInit {

  arrayTeamInfo: Array<any> = [];

  constructor(private apiService: ApiService,
              private router: Router,
              private route: ActivatedRoute) { }

  ngOnInit(): void {
    const id = this.route.snapshot.params['id'];

    this.apiService.getTeamFromServe(id).subscribe(
      data => {
        let arrayData = [];
        arrayData = JSON.parse(data);
        this.arrayTeamInfo = arrayData;
        console.log(this.arrayTeamInfo);
      }, err => {
        this.arrayTeamInfo = JSON.parse(err.error).message;
      }
    )
  }
}

结果consol.log:

activeCompetitions: []
address: "null Rio de Janeiro, RJ null"
area: {id: 2032, name: "Brazil"}
clubColors: "Red / Black / White"
crestUrl: "https://crests.football-data.org/1783.svg"
email: null
founded: 1919
id: 1783
lastUpdated: "2020-09-10T02:18:46Z"
name: "CR Flamengo"
phone: null
shortName: "Flamengo"
squad: []
tla: "FLA"
venue: "Estadio Jornalista Mário Filho"
website: "https://www.flamengo.com.br/pagina-inicial-basquete"

团队-detail.component.html :

<h1> 
    {{ arrayTeamInfo.name }} 
</h1>

每个属性都会出现此问题,例如(地址、clubColors、电子邮件...)。 我收到这个错误: Error: src/app/teams/team-detail/team-detail.component.html:9:38 - error TS2339: Property 'name' does not exist on type 'any[]'.

但是,如果我在我的 html 文件上执行此操作,它就可以工作了:

<h1> 
    {{ arrayTeamInfo['name']}} 
</h1>

我只是随机使用了这个语法,我不明白为什么我必须在这里这样做,而在我创建的所有其他组件(具有完全相同的结构)中我没有问题...

我是不是遗漏了什么?

在组件class中,你说:

arrayTeamInfo: Array<any> = []

所以arrayTeamInfo肯定是一个数组;它的名字以“数组”开头,它有一个数组类型(Array<any>any[] 相同),默认值是一个错误。非常清楚。您在接收数据时加强这一点:

let arrayData = [];
arrayData = JSON.parse(data);
this.arrayTeamInfo = arrayData;

空数组值未使用,但确实将 arrayData(再次“数组”!)的类型设置为 any[]。这 100% 是一个数组,当然不会 不是 数组。正确的?但随后在 模板 中,您可以:

<h1> 
    {{ arrayTeamInfo.name }} 
</h1>

数组没有 名称,因此当编译器对其进行类型检查时,它自然会有点混乱。因此(完全准确)错误:

Property 'name' does not exist on type 'any[]'.

在你的问题中,你显示的团队信息非常不是数组,并说 arrayTeamInfo['name'] 确实 有效,所以问题是:你为什么这么花钱花了很多时间说服编译器你的值将是一个数组,如果不是的话?


那你是怎么解决的呢?首先,您应该在代码库的某处表达团队信息的实际形状:

interface Team {
  name: string;
  area: {id: number; name: string};
  /* ...other props */
}

然后您可以在从服务器获取数据时实际使用它,这样您的其余代码就知道它应该期望接收什么 - 指定方法的 return 类型,并使用HttpClient#get 的通用类型参数(参见 https://angular.io/guide/http#requesting-a-typed-response):

export class ApiService {

  constructor(private httpClient: HttpClient) { }

  getTeamFromServe(id: number): Observable<Team> {
    return this.httpClient.get<Team>(  // <- set this
      `https://api.football-data.org/v2/teams/${id}`,
      { 
        headers: {'X-Auth-Token': 'XXXXXXXXXXXXXXXXX'},
        /* other options restated defaults or were wrong */
      }
    )
  }
} 

最后,在您的组件中,属性 的类型实际上应该反映您计划分配给它的内容,以便编译器可以检查您编写的内容是否有意义:

@Component({
  selector: 'app-team-detail',
  templateUrl: './team-detail.component.html',
  styleUrls: ['./team-detail.component.scss']
})
export class TeamDetailComponent implements OnInit {

  teamInfo?: Team;  // <- no initial value, so undefined until request completes

  constructor(private apiService: ApiService,
              private router: Router,
              private route: ActivatedRoute) { }

  ngOnInit(): void {
    const id = this.route.snapshot.params['id'];

    this.apiService.getTeamFromServe(id).subscribe(data => {
      this.teamInfo = data;  // <- data is typed as Team, so the compiler's happy
    })
  }
}
<h1> 
    {{ teamInfo?.name }}
    <!-- safe navigation handles undefined default --> 
</h1>

(请注意,组件不再需要 JSON.parse 来自服务的数据 - 拥有单独服务的要点是从表示中抽象出传输层的细节层,因此将类似“我们将数据作为 JSON 字符串获取”之类的内容泄漏到组件中是没有帮助的。)

另一种选择是更多地使用可观察对象,使用 | async 管道而不是需要安全导航;我几年前写过 on my blog(使用旧的 Http 语法,但这些想法仍然有用)。