【问题标题】:Angular & TypeScript - Creating interfaces for nested objectsAngular & TypeScript - 为嵌套对象创建接口
【发布时间】:2020-08-21 08:32:28
【问题描述】:

如果尝试将一些接口应用于我从 API 获得的 JSON 响应,我已经花费了很多时间。编译后它确实在浏览器中工作,但我的 IDE vs 代码给了我这个错误 未定义标识符“title”。 'RoomItem[]' 不包含这样的成员

它确实显示了元素,我的 vs 代码只是在视图中用红色下划线标记了数据属性。与此同时,我的终端也会向我弹出这个警告。

AngularCompilerPlugin 中的警告:分叉类型检查器意外退出。回退到对主线程进行类型检查。

任何人都可以帮助我,我将非常感激 - 祝开发人员愉快!

// JSON Response

area: "21 - 28 m²"
day_price_flex: "1647.00"
day_price_normal: "1318.00"
description: "Vores flotte superiorværelser tilbyder mere plads til at slappe af på efter en lang dag på ferien. Se en film på TV'et eller nyd lidt afslapning i badekarret."
facilities: (12) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
id: "2"
images: [{…}]
num_facilities: 12
num_images: 1
num_persons: "2"
title: "Superior"

// Facilities

facilities: Array(12)
0: {id: "1", title: "Elkedel med kaffe/te", category: "Generelt udstyr"}
1: {id: "2", title: "Fri WiFi", category: "Generelt udstyr"}
2: {id: "3", title: "Hårtørrer", category: "Generelt udstyr"}
3: {id: "4", title: "Ikke-ryger", category: "Generelt udstyr"}
4: {id: "5", title: "Luftkøling", category: "Generelt udstyr"}
5: {id: "6", title: "Minibar", category: "Generelt udstyr"}
6: {id: "7", title: "Mørklægningsgardiner", category: "Generelt udstyr"}
7: {id: "8", title: "Pengeskab", category: "Generelt udstyr"}
8: {id: "9", title: "Strygebræt og strygejern", category: "Generelt udstyr"}
9: {id: "10", title: "Fransk altan (tilgængelig i nogle værelser)", category: "Generelt udstyr"}
10: {id: "25", title: "To separate enkeltsenge", category: "Senge"}
11: {id: "26", title: "King-size seng", category: "Senge"}

// Images

0: {id: "75", title: "Superior Soveplads ©", image: "/images/room-superior-bedroom.jpg"}


// HTML / View

<section *ngIf="http.data | async as data">
    <article>
        <h2>{{data.title}}</h2>
        <h5>{{data.area}}</h5>
        <p>{{data.description}}</p>
    </article>
</section>
// http.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { map, catchError, shareReplay } from 'rxjs/operators';

interface Facilities {
  id?: string;
  title?: string;
  category?: string;
}

interface Images {
  id?: string;
  title?: string;
  image?: string;
}

interface RoomItem {
  id: string;
  title: string;
  description: string;
  num_persons: string;
  area: string;
  day_price_normal: string;
  day_price_flex: string;
  num_images: number;
  images?: Images[];
  num_facilities: number;
  facilities?: Facilities[];
}

interface Response {
  status: boolean;
  error: string;
  item?: RoomItem[];
  items?: RoomItem[];
}


const CACHE_SIZE = 1;

@Injectable({
  providedIn: 'root'
})
export class HttpService {
  private cache$: Observable<RoomItem[]>;

  constructor(private http: HttpClient) {}
  
   get data() {
    if (!this.cache$) {
      this.cache$ = this.requestRoom(2).pipe(shareReplay(CACHE_SIZE));
    }
    
    return this.cache$;
   }

   private requestRoom(id) {
     return this.http.get<Response>(`https://api.mediehuset.net/overlook/rooms/${id}`).pipe(
       map(response => response.item ? response.item : response.items)
     );
   }

}

问题是,我现在尝试删除我的类型的数组部分, 但它不会编译,那是因为我在它上面使用了一个 map 运算符 - 如果它不是一个数组,这是不可能的..

// If i change my cache observable to not having it:

Observable<RoomItem>

// I had to change it in my Response type as well..

interface Response {
  status: boolean;
  error: string;
  item?: RoomItem;
  items?: RoomItem;
}

// I actually also tried with RoomItem<Object>, with compilation success but no results on the functioning part of it.

正如我写的那样,那次它不会工作 - 因为编译错误.. 那么该怎么办,只有我的 IDE 告诉我我错了,它仍然编译并通过显示我的物品?

因此,当我在 IDE 中执行错误代码弹出红色下划线时,我想我不应该担心以某种方式编写有意义的代码。 这是出于测试目的,当然我应该让接口有自己的文件,以便在其他各自的使用位置导入。

【问题讨论】:

  • 您的回复中似乎添加了RoomItem[]而不是RoomItem
  • 感谢您的输入,但是当我尝试这样做时,我在 src/app/services/http.service.ts:75:7 - 错误 TS2322 中得到 CANNOT GET/ ERROR: Type 'Observable' 不可分配给类型 'Observable'。输入“房间项目 | RoomItem[]' 不可分配给类型 'RoomItem[]'。 “RoomItem”类型缺少“RoomItem[]”类型中的以下属性:长度、弹出、推送、连接和 26 多个。 75 this.cache$ = this.requestRoom(2).pipe(shareReplay(CACHE_SIZE));如果我尝试在有 RoomItem[] 的地方删除“[]”,那么它也不会工作..

标签: angular typescript interface


【解决方案1】:

在服务中,您将根据条件返回不同的响应,一个项目{ } 或项目[ ]。所以你将它的返回类型转换为Observable&lt; RoomItem | RoomItem[]&gt;

服务

get data(): Observable< RoomItem | RoomItem[]> {
        if (!this.cache$) {
            this.cache$ = this.requestRoom(2).pipe(shareReplay(CACHE_SIZE));
        }

        return this.cache$;
    }

    private requestRoom(id) {
        return this.http
            .get<Response>(`https://api.mediehuset.net/overlook/rooms/${id}`)
            .pipe(map((response) => (response.item ? response.item : response.items)));
    }

HTML

<section *ngIf="http.data | async as data">
    <article *ngIf="!isDataAnArray(data); else displayArrayData">
        <h2>{{data.title}}</h2>
        <h5>{{data.area}}</h5>
        <p>{{data.description}}</p>
    </article>
    <ng-template #displayArrayData>
      <article>
       <div *ngFor="let item of data">
            <h2>{{item.title}}</h2>
            <h5>{{item.area}}</h5>
            <p>{{item.description}}</p>
        </div> 
    </article>
    </ng-template>
</section>

组件

isDataAnArray(data: RoomItem | RoomItem[]){
        retun Array.isArray(data);
    }

接口定义

interface Response {
  status: boolean;
  error: string;
  item?: RoomItem;
  items?: RoomItem[];
}

【讨论】:

  • 我尝试更改您描述的内容,但仍然有红色下划线 - 未定义标识符“标题”。 '房间物品 | RoomItem[]' 不包含这样的成员
  • @Malthe,将Response中的类型更改为item?: RoomItem;,查看更新后的答案
猜你喜欢
  • 2018-11-05
  • 2017-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 2021-03-30
  • 2019-10-28
  • 2019-12-24
相关资源
最近更新 更多