错误 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
语法,但这些想法仍然有用)。
我搜索了 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
语法,但这些想法仍然有用)。