Angular の TypeScript レスポンスモデルと型エラー
NodeJSサーバーを使用したローカルのMEANスタックアプリで、私のエンドポイントのレスポンスはPostの配列を返します:
{
"message": "Posts fetched successfully!",
"posts": [
{
"_id": "618b22ff9e50776ed377c4eb",
"title": "aaaaaaaaaaaaaa",
"body": "xxxxxxxxxxxxx",
"__v": 0
},
]
}
レスポンスモデルを持つAngularサービス:
export interface PostResponse {
message: string;
posts: Post;
}
getPosts(): Observable<PostResponse> {
return this.http.get<PostResponse>(this.postsUrl + '/api/posts');
}
PostComponentは上記のPostserviceを注入します:
export interface Post {
id: number;
title: string;
body: string;
}
export class PostsComponent implements OnInit {
posts: Post[] = [];
constructor(private postService: PostService) {}
ngOnInit() {
this.postService
.getPosts()
.pipe(
map((data) => {
console.log('data : ', data.posts._id); // vide #1
return {
id: data.posts.id, // _id error <HERE>
title: data.posts.title,
content: data.posts.body,
};
})
).subscribe((response) => {
this.posts = response; // error <HERE>
console.log('posts updated : ', this.posts);
});
}
質問。
Q-1:私のコンポーネントでレスポンスデータをマッピングする際、必要なプロップは data.posts.id です。data.posts._id ではありません。しかし、ストリームデータは次の通りです:#1 { "_id": "618b22ff9e50776ed377c4eb", "title": "aaaaaaaaaaaaaa", "body": "xxxxxxxxxxxxx", "__v": 0 },
もし私が _id を使用すると、型 'Post' に '_id' プロパティは存在しないというエラーが発生します
これは私のインターフェイス PostResponse のせいですか?
_id は私の Mongo データベースから来ています。フロントエンドの構造に合わせるために、_ID ではなく ID を使っているので、レスポンスデータを強制的に変換する必要があると考えていました。
Q-2: subscribeの中で、this.posts=response とするとエラーが出ます:
型 '{ id: number; title: string; content: string; }' には型 'Post[]' から次のプロパティが欠けています: length、pop、push、concat、その他26個。ts(2740)
回答 #1
Q1:はい、それは getPosts() で使用している PostResponse インターフェースのためです。そのインターフェースの Posts 属性は Post インターフェースを参照しており、つまり posts オブジェクトのすべての属性は Post インターフェースから来ています。次のように修正してください:
export interface Post {
_id: string;
title: string;
body: string;
}
Q2:PostResponse から JSON レスポンスをマッピングしていて、'post' 属性の値ではないので、配列の代わりにオブジェクトが返されます。次のように試してください:
this.postService
.getPosts()
.pipe(
map((data) => {
return data.posts.map(v => {
_id: v._id,
title: v.title,
content: v.body,
})
})
).subscribe((response) => {
this.posts = response;
});
そして、PostResponse の post 属性の型を配列にしてください:
export interface PostResponse {
message: string;
posts: Post[];
}
回答 #2
私が理解している限り、あなたのインターフェースは間違っています。
export interface PostResponse {
message: string;
posts: Post[];
}
export interface Post {
_id: string;
title: string;
body: string;
}
それらは正しいインターフェースのようです。
データを取得するには、次の手順を行う必要があります:
this.postService
.getPosts()
.subscribe((response) => {
this.posts = response?.posts;
});
または
this.postService
.getPosts()
.subscribe((response) => {
this.posts = response?.posts?.map(res => {
return {
_id: res.id,
title: res.title,
body: res.body,
}
});
});
