Angular使用async、keyvalue管道时出现Property 'title'不存在错误如何解决?
报错原因
- 接口返回结构与类型声明不匹配:服务中
squeezePosts方法声明返回Observable<Post[]>数组类型,但实际后端返回的是以数字字符串为key、Post对象为value的键值对对象,TypeScript泛型仅做编译期类型提示,不会做运行时结构转换,实际拿到的并不是数组。 - 错误使用
keyvalue管道:对数组使用keyvalue管道时,管道会遍历数组的所有可枚举属性,包括数组自带的length(数字类型)、push/pop等原型方法,导致遍历得到的post.value可能是数字、函数等非Post类型,触发类型报错:
Property 'title' does not exist on type 'number | Post | (() => string) | ...'.
Property 'title' does not exist on type 'number'.
解决办法
提供3种可选方案,按需求选择即可:
方案1:前端适配现有后端返回
不需要修改后端逻辑,仅调整前端类型声明即可:
- 修正服务方法的返回类型:
squeezePosts(analysisType: string, limit: number): Observable<Record<string, Post>>{ // 把http.get的泛型从Post[]改为Record<string, Post> return this.http.get<Record<string, Post>>(`${this.url}${analysisType}/"none"/none"/${limit}`) .pipe( catchError(this.handleError<Record<string, Post>>('squeezePosts', {})) ); }
- 修正组件中
posts$的类型声明:
posts$!: Observable<Record<string, Post>>;
现有模板代码无需修改,keyvalue管道适配对象遍历,此时post.value会被正确识别为Post类型,报错消失。
方案2:前端将返回对象转为数组
如果更习惯用数组遍历,调整逻辑如下:
- 在服务方法中增加结构转换逻辑:
import { map } from 'rxjs'; squeezePosts(analysisType: string, limit: number): Observable<Post[]>{ return this.http.get<Record<string, Post>>(`${this.url}${analysisType}/"none"/none"/${limit}`) .pipe( map(res => Object.values(res)), // 提取对象所有value转为Post数组 catchError(this.handleError<Post[]>('squeezePosts', [])) ); }
- 删掉模板中的
keyvalue管道:
<div class="posts-div"> <div *ngFor="let post of posts$ | async"> {{ post.title }} </div> </div>
方案3:修改后端返回结构
如果后端可调整,直接返回数组格式即可:
[ { "title": "0 - My title test", "selftext": "0 - My selftext test, My selftext test. My selftext test ..." }, { "title": "1 - My title test", "selftext": "1 - My selftext test, My selftext test. My selftext test ..." } ]
此时仅需删掉模板中的| keyvalue管道,原有其他代码无需修改即可正常运行。
注意:你现有服务代码中的请求URL存在笔误,${analysisType}/"none"/none"/${limit} 处第二个none后多了一个双引号,后续接口调试时可注意修正。
内容的提问来源于stack exchange,提问作者Ano
相关产品推荐
相关产品推荐

