Angular访问JSON对象数据报错:'list'属性不存在于Weather[]类型
问题排查与解决方案
首先,咱们直接说核心问题:你遇到的编译错误Property 'list' does not exist on type 'Weather[]',本质是类型定义错误 + 数据结构不匹配导致的,下面一步步拆解修复:
1. 直接错误原因:数组类型误用
你把eval定义成了Weather[](Weather对象的数组),但数组本身没有list属性——你试图直接访问this.eval.list,就像在说“给我这个箱子的抽屉”,但其实你手里是一整排箱子,得先拿出第一个箱子,再找它的抽屉。
不过这只是表面问题,更大的问题是你的Weather类结构和API返回的数据完全不匹配。
2. 根本问题:类型定义与API返回结构不符
OpenWeatherMap的Forecast API返回的是单个对象,这个对象里包含list数组(存放每小时/每日预报),而你的Weather类把层级完全搞反了,还错误地把组件里的变量定义成了数组类型。
先看API返回的简化结构:
{ "cod": "200", "city": {"id": 5417598, "name": "Denver"}, "list": [ {"main": {"temp": 72, "humidity": 45}}, // 更多预报项 ] }
修正类型定义(建议用接口更轻量)
替换你原来的Weather类,改成匹配API结构的接口:
// src/app/models/weather.ts export interface WeatherMain { temp: number; humidity: number; // 按需添加其他字段如temp_min、temp_max } export interface WeatherForecastItem { main: WeatherMain; // 按需添加dt、weather等其他API返回字段 } export interface WeatherResponse { cod: string; // API返回的cod是字符串,比如"200",不是对象! city: { id: number; name: string; }; list: WeatherForecastItem[]; }
如果一定要用类,必须初始化嵌套对象避免运行时错误:
export class WeatherResponse { cod: string = ''; city: { id: number; name: string } = { id: 0, name: '' }; list: { main: { humidity: number; temp: number } }[] = []; constructor(cod?: string, cityId?: number, cityName?: string) { this.cod = cod || ''; if (cityId && cityName) { this.city.id = cityId; this.city.name = cityName; } } }
3. 修正组件代码
把组件里的数组类型改成单个对象,并修复属性访问逻辑,同时增加空值检查避免运行时错误:
import { WeatherRestService } from './../weatherRest.service'; import { Component, OnInit } from '@angular/core'; import { WeatherResponse } from '../models/weather'; @Component({ selector: 'app-widget', templateUrl: './widget.component.html', styleUrls: ['./widget.component.css'] }) export class WidgetComponent implements OnInit { // 改为单个对象,不是数组 weather: WeatherResponse; eval: WeatherResponse; light = 0; constructor(public rest: WeatherRestService) { } ngOnInit() { this.index(); } index() { this.rest.index().subscribe( weather => { this.weather = weather; this.eval = this.weather; this.evaluate(); }, err => { console.error('error retrieving properties'); console.error(err); } ); } display() { console.log(this.weather); this.evaluate(); } evaluate() { // 先检查数据是否存在,避免空引用崩溃 if (!this.eval || !this.eval.list || this.eval.list.length === 0) { console.warn('No weather data available'); return; } // 正确访问第一个预报项的温度 const temp = this.eval.list[0].main.temp; if (temp < 40) { this.light = 2; } else if (temp >= 40 && temp < 80) { this.light = 3; } else if (temp >= 80) { this.light = 1; } console.log(this.eval); console.log(temp); } }
4. 修正服务代码
调整HTTP请求的返回类型,去掉不必要的请求头(OpenWeatherMap不需要这些):
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { WeatherResponse } from '../models/weather'; @Injectable({ providedIn: 'root' }) export class WeatherRestService { private url = 'http://api.openweathermap.org/data/2.5/forecast?id=5417598&APPID='; private auth = 'xxxxxxxxxxxxxxxxxx'; constructor(private http: HttpClient) { } index() { let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'application/json'); headers = headers.append('Accept', 'application/json'); // 以下几个头OpenWeatherMap不需要,直接去掉 // headers = headers.append('Authorization', 'Basic '); // headers = headers.append('Content-Encoding', 'none'); // headers = headers.append('Origin', 'http://localhost:4200'); // 返回正确的类型,不是any[] return this.http.get<WeatherResponse>(this.url + this.auth + '&units=imperial'); } }
额外提醒
- 原始
Weather类的构造函数会直接报错,因为this.cod未初始化就访问this.cod.city,必须确保嵌套对象先被赋值。 - 优先用接口定义数据类型,Angular会自动把HTTP响应映射到接口,不需要手动实例化类。
- 访问嵌套属性前一定要做空值检查,避免数据未加载完成时出现崩溃。
内容的提问来源于stack exchange,提问作者Rob Thompson
相关产品推荐
相关产品推荐

