Search code examples
arraysangulartypescriptmultidimensional-arrayangular-signals

How do I return a nested object array using a Signal in Angular/Typescript?


In my Angular/Typescript code, I have a nested object array that I am trying to return(filter) based on the object property which has the value === 'event'.

I don't know what I'm missing but for some reason, it won't return the nested object array but instead keeps telling me my variable is of type CalendarModel[] which is the parent.

I added :{types} to the variables/filters to show you what Angular tells me the variable types are.

getAllEvents: Signal<CalendarModel[]> = computed(() => this.dataService.allInformation()?.allCalendarInformation?.filter(calendar: CalendarModel => calendar?.events?.filter(event: CalendarEvent=> event.type === 'event').filter(event: CalendarEvent => {
    return new Date(event.date).getTime() >= new Date().setHours(0, 0, 0, 0);
  }))
);

Here is my model structure:

allCalendarInformation: CalendarModel[];
export interface CalendarModel {
  date: Date;
  events: CalendarEvent[];
}
export interface CalendarEvent {
  imageUrl?: string
  title: string;
  date?: Date;
  location?: string;
  time?: string;
  description: string;
  type?: string;
  featured?: boolean;
}

Am I missing something?

I'm drilling down into events and trying to get all the events that have the type === 'event' but Typescript keeps telling me my overall object from getAllEvents is of type CalendarModel[]. Shouldn't it be CalendarEvent[]?

Please help me understand what I am doing wrong.

I have multiple other filtered objects throughout my project and they work but I'm doing something wrong here.


Solution

    1. Iterate all CalendarModel objects and combine the CalendarEvent into an array via .reduce().

    2. Filter the CalendarEvent object by type and date.

    getAllEvents: Signal<CalendarEvent[]> = computed(() =>
      this.dataService.allInformation()
        ?.allCalendarInformation
        ?.reduce(
          (acc: CalendarEvent[], cur: CalendarModel) => [...acc, ...cur.events],
          [] as CalendarEvent[]
        )
        .filter(
          (event: CalendarEvent) =>
            event.type === 'event' &&
            event.date &&
            new Date(event.date).getTime() >= new Date().setHours(0, 0, 0, 0)
        ))
    );
    

    Demo @ StackBlitz