Невозможно использовать свойство объекта в шаблонах при импорте из другого класса

Я новичок в angular и столкнулся с проблемой, когда Angular16 не отображает свойства объекта, определенного во внешнем классе. Посмотрите на следующую иллюстрацию.

Я определил класс следующим образом. Я использую этот класс для хранения данных, которые получаю от серверной части. Эти значения повторно используются в других компонентах.

export class StaticClass {
    static dict:{[key: string]: Array<object> } = {
        1: [],
        2: [
            { id: 1, text: "Hello" },
        ],
        3: [],
}}

Затем я импортирую этот класс, чтобы использовать сохраненные значения.

import { Component } from '@angular/core';
import { StaticClass } from 'src/app/utils/calendarEvents';

@Component({ ..<omitted>.. })
export class SampleViewComponent {
    staticClass = StaticClass;
    temp = [{ id: 1, text: "Hello" }]


   constructor(){
        console.info(this.staticClass.dict[2])
        console.info(this.temp)
    }
}

Здесь оба вывода консоли отображают одно и то же. Однако TS выдает мне ошибку, когда я пытаюсь отобразить значения в staticClass.

<div *ngFor = "let i of this.staticClass.dict[2]">
    {{ i.id }}
</div>

Свойство «id» не существует для типа «object».ngtsc(2339)

Но он отлично работает при использовании temp.

<div *ngFor = "let i of this.temp">
    {{ i.id }}
</div>

Вопросы:

  1. Как мы можем исправить вышеуказанную проблему? В чем разница между temp и staticClass.dict[2]
  2. Есть ли лучший способ сохранить значения, которые я получаю от бэкэнда? Поскольку они будут временными и будут постоянно меняться, я не хочу использовать локальное хранилище браузера.

В сообществе Stack Overflow мы не рекомендуем задавать несколько вопросов в одном сообщении, если они не связаны между собой. Таким образом, ваш вопрос 2, в котором спрашивается, как хранить данные в приложении Angular, должен быть в другом сообщении, а не в том же сообщении, что и ваш основной вопрос. Meta.stackoverflow.com/questions/402523/…

Yong Shun 06.07.2024 03:47

Привет @YongShun Принято к сведению. Спасибо

wtc claw 06.07.2024 16:43
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
2
58
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Разница между значениями:

  1. в StaticClass: определяется как тип Array<object>.

  2. для переменной temp: определяется как { id: number; text: string; }[].

Хотя в целом мы понимаем, что оба они являются массивами объектов, но компилятор обращается с ними по-разному. object реализует/расширяет интерфейс Object. Для справки: «любой» или «Объект»

Если вы знаете структуру вашего объекта и она единообразна (одна и та же структура применяется ко всем объектам), вы можете определить тип как:

export class StaticClass {
  static dict: { [key: string]: Array<{id: number; text: string}> } = {
    1: [],
    2: [{ id: 1, text: 'Hello' }],
    3: [],
  };
}

Или вы можете использовать any, чтобы компилятор пропускал проверку типов.

export class StaticClass {
  static dict: { [key: string]: Array<any> } = {
    1: [],
    2: [{ id: 1, text: 'Hello' }],
    3: [],
  };
}

Демо @ StackBlitz

Привет @Ён Шун! Большое спасибо. Это помогло. Поэтому лучше определить тип массива или позволить ему быть любым. Есть ли какой-либо вариант использования, когда полезно определить тип как Array<object>?

wtc claw 06.07.2024 17:10

Насколько я знаю, тип object используется при попытке проверить, что значение не является примитивным: typescriptlang.org/docs/handbook/release-notes/…

Yong Shun 07.07.2024 03:30

Попробуйте использовать !, чтобы избежать ошибки, не инициированной объектом.

<div *ngFor = "let i of this.temp">
    {{ i!.id! }}
</div>

@ Ён Шун уже дал правильный ответ. Несмотря на то, что я настоятельно рекомендую использовать полный набор функций машинописного текста, используя типы/интерфейсы.

Этого можно добиться следующим образом:

статическийкласс.ts

export interface Parent {
  [key: string]: Array<Something>;
}

export interface Something {
  id: number;
  text: string;
  additionalInfo?: string; // optional parameter
}

export class StaticClass {
  static dict: Parent = {
    1: [],
    2: [{ id: 1, text: 'Hello' }],
    3: [{ id: 5, text: 'asf', additionalInfo: 'great product!' }],
    // 4: [{ id: 5, txt: 'asf'}], // ❌ typo in 2nd parameter would throw TS-error
  };

Благодаря этому (а) при компиляции могут быть обнаружены ошибки типа (б) какой-то пользователь ваших компонентов знает, какие данные он может ожидать.

мой.компонент.ц

@Component({
  /* ... */
  templateUrl: `my.component.template.html`,
})
export class App {
  dict: Parent = StaticClass.dict; // ✅ dev sees whats going on on first sight
}

мой.компонент.шаблон.html

@for(i of this.dict[2]; track i.id) {
    {{ i.id }} <!-- ✅ dev knows id exists without checking StaticClass -->
}

Stackblitz

Другие вопросы по теме