Search code examples
angulartypescriptdictionarysetkey

Typescript - How to set the value of an object key in a Map


I have a Map which takes a Lecture as Key and an Array of Todos as value.

lecturesWithTodos: Map<Lecture, Todos[]> = new Map<Lecture, Todos[]>();

Now I first set the key of this Map without any value (because I get the Todos later).

student.semester.lectures.forEach((lecture) => {
    this.lecturesWithTodos.set(lecture, []);
});

Now I just would like to set my Todos to its specific Key.

todos.forEach((todo) => {
   this.lecturesWithTodos.get(lecture).push(todo);
});

But at this point it is always saying "Cannot read property 'push' of undefined". I know I can get it done, when I am using a string as Key, but I would like to use my Object instead, because it makes things easier for me later.

Is there a way how to get the get-Method working on this lecture object?


Solution

  • Although it would be difficult to retrieve elements from the map later on, one way to achieve your objective is illustrated below.


    Assuming that your types are as follows (change them as per your requirement)

    interface Todos {
      id: number;
      name: string;
    }
    
    interface Lecture {
      id: number;
      name: string;
    }
    

    The given data:

     lectures: Lecture[] = [
        { id: 100, name: 'ENG' },
        { id: 200, name: 'PHY' },
        { id: 300, name: 'BIO' }
      ];
    
      todos: Todos[] = [
        { id: 100, name: 'Add' },
        { id: 100, name: 'Sub' },
        { id: 300, name: 'Mul' }
      ];
    

    Logic to create the map

    ngOnInit() {
       this.lectures.forEach(lecture => {
          this.lecturesWithTodos.set(lecture, []);
       });
    
       this.todos.forEach(todo => {
          const findLecture = this.findById(todo.id);
          const findAllTodos = this.findTodos(todo.id);
    
          if (findLecture && findAllTodos) {
            // implies that there is a previous todo added earlier
            this.lecturesWithTodos.set(findLecture, [...findAllTodos, todo]);
          } else if (findLecture) {
            // implies that its a new todo being set
            this.lecturesWithTodos.set(findLecture, [todo]);
          }
      });
    
    }
    
    /** Used to find Lecture based on todo id **/
    findById(id: number) {
        return Array.from(this.lecturesWithTodos.keys()).find(e => e.id === id);
    }
    
    /** Used to find all previous todos based on todo id **/
    findTodos(id: number) {
        // todos is a 2D array
        let todos = Array.from(this.lecturesWithTodos.values());
    
        // convert to 1D array for finding values from it
        return [].concat.apply([], todos).filter(e => e.id === id);
    }