Search code examples
angularangular16

Unable to use an Object's property in templates when imported from a diferent class


I am new to angular and i am facing issue where Angular16 does not display the properties of an object when defined in an external class. Check out the following illustration.

I have defined a class in the following manner. I use this class to store data i receive from the backend. These values are reused in other components.

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

I then import this class to use the values stored.

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.log(this.staticClass.dict[2])
        console.log(this.temp)
    }
}

Here, both console outputs displays the same thing. However, TS throws me an error when i try to display the values in staticClass.

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

Property 'id' does not exist on type 'object'.ngtsc(2339)

But it works just fine when using temp.

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

Questions:

  1. How can we rectify the above issue? What is different between temp and staticClass.dict[2]
  2. Is there a better way to store the values i receive from backend? Since these are going to be temporary and changing throughout, i don't want to use browser local storage.

Solution

  • The difference between the values:

    1. in the StaticClass: Defined as Array<object> type.

    2. for the temp variable: Defined as { id: number; text: string; }[].

    Even though in common, we understand that both of them are arrays of objects, but the compiler treats them differently. The object implements/extends the Object interface. For your reference: 'any' vs 'Object'

    If you know the structure of your object and it is consistent (same structure applied to all objects), you can define the type as:

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

    Or you can work with any so that the compiler skips the type-checking.

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

    Demo @ StackBlitz