ウェブサイト検索

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,
               }
             }); 
       });