Creating dynamic keys to insert objects

In my coding project, I am dealing with an empty array, a value, and an object. Since there are multiple objects involved, I want to organize them into categories. Here is an example of what I envision:

ARRAY 
  KEY
    OBJECT
    OBJECT
  KEY
    OBJECT

Initially, the array is empty as shown below:

public serviceTable: Services[] = [];

This is the interface for the array objects:

export interface Services {
  details:
    {
      service: string,
      description: string
    }
}

The object I receive from result looks like this:

data: {
  details: [
    {
      service: this.formMain.get('service')?.value,
      description: this.formMain.get('description')?.value
    }
  ]
}

Lastly, here is how I try to define the dynamic key for the array and its objects:

dialogRef.afterClosed().subscribe(result => {
  if (result) {
   if (!Object.keys(this.serviceTable)[result.section]) {
     // No section found, lets create it ...
     this.serviceTable[this.randomNumber] = [result];
     console.log(this.serviceTable, 'ServiceTable')
   }
   else {
     this.serviceTable[this.randomNumber].push()
   }
}

While the if-statement works fine, I encounter an issue with the else-statement leading to the error:

TS2339: Property 'push' does not exist on type 'Services'.

The error possibly occurs because

this.serviceTable[this.randomNumber]
is not recognized as an array.

If the key (this.randomNumber) doesn't already exist in the array, it will be created. However, if it does exist, I intend to add the new object under the same key.

Hence, I aim to iterate through the array and access all objects associated with a specific key, like this:

for (let item of this.serviceTable[3]) { // The number can also be replaced by a string, e.g., this.serviceTable['myCategory']
  console.log(item.service); // This should display all services linked to the key '3'
}

How can I achieve this functionality?


Check out an example of my code on StackBlitz.

Answer №1

Your primary issue lies within your user interface. While keeping the current setup, consider incorporating the following additional line:

export interface Sections extends Array<Services> {}

Furthermore, it might be necessary to update

public serviceTable: Services[] = [];

to

public serviceTable: Sections[] = [];

By utilizing an array in this manner, you can confidently employ

this.serviceTable[this.randomNumber].push(result)
without encountering any issues.

In alignment with your objective, here is a suggested approach for iterating through the array to extract objects based on a specific key:

// Similar to your existing code, but remember to include 'details'
for (let item of this.serviceTable[3]) {
 console.log(item.details.service);
}

Answer №2

Your code on Stackblitz is different from the code you have shown here, particularly in the definition of the Services interface. This difference is causing the issues you are facing (which also explains why your code was not compiling as expected)

In your question, the Services interface is defined like this:

export interface Services {
  details:
    {
      service: string,
      description: string
    }
}

However, in Stackblitz, it looks like this:

export interface Services {
  [details:number]:
    {
      service: string,
      description: string
    }
}

This results in a completely different data type. An instance of the first interface would look like this:

{ 
  details: {
    service: "foo",
    description: "bar"
  }
}

While an instance of the second interface would look like this:

{ 
  1: {
    service: "foo",
    description: "bar"
  }
}

In the second interface, the keys are numbers, making it similar to an array. This is why you were able to perform the assignment:

this.serviceTable[this.randomNumber] = [result];

However, since it's not actually an array, it does not have a push function (even though it may work at runtime because you are assigning a real array). This discrepancy causes a compilation error.

You also have a third type related to this issue, regarding the type of your result object:

data: {
  details: [
    {
      service: this.formMain.get('service')?.value,
      description: this.formMain.get('description')?.value
    }
  ]
}

If you try to assign

this.serviceTable[this.randomNumber] = [result];
, you will be trying to assign an incompatible array structure, as result contains a data property which is not present in the other types mentioned. The easiest solution might be to define the serviceTable as an array of arrays and use the original definition of the Services interface from your question rather than Stackblitz.

When creating the result object, you may need to adjust it to correctly match the updated structure, such as:

let result = {
  details: {
    service: this.formMain.get('service')?.value,
    description: this.formMain.get('description')?.value
  }
}

Or

let result = {
  data: {
    details: {
      service: this.formMain.get('service')?.value,
      description: this.formMain.get('description')?.value
    }
  }
}

Finally, if you intend to use push() with a value, that should also work with the modified definitions of serviceTable and result.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Invalid component exception: The element type is not valid in React Native

In my React Native App.js file, I have included the following code snippet import { StatusBar } from 'expo-status-bar'; import React, { useRef } from 'react'; import { StyleSheet, Text, View, Canvas } from 'react-native'; impo ...

Experiencing problems with the Datepicker and cloning functionality in JQuery?

This is the section of code responsible for cloning in JavaScript. $(document).on("click", ".add_income", function () { $('.incomes:last').clone(true).insertAfter('.incomes:last'); $(".incomes:last").find(".income_date_containe ...

Executing a method to retrieve a value from an empty function in Node.js

I am currently dealing with the code snippet below: function done(err, file) { //handling of code here return "test"; } function process() { retext() .use(keywords) .process(sentence, done); return val; } The proce ...

getJSON takes precedence over other tasks

I am having a challenge retrieving data in JSON format from the server and displaying it dynamically in a table. The code runs without errors and successfully fetches the data, but for some reason, nothing appears in the table. I suspect there may be an ...

Leveraging Firebase Dynamic Links through JavaScript

Currently exploring options for implementing Dynamic Links. Firebase Dynamic Links seem promising, but the lack of support for Cordova/ ionic apps is concerning. Is there any plan to add this in the future? Are there any other alternatives that you would ...

Click event not triggered when transitioning to Service section in Thinkster tutorial

I've been following a tutorial on MEAN stack development () and I encountered an issue after incorporating Angular Services. For some reason, the function incrementUpvotes stopped working and I'm struggling to identify the cause. Since I'm r ...

Accessing JSON data from a URL in AngularJS

Just dove into the world of fetching and displaying JSON data in my AngularJS app for the first time, but unfortunately, no data is showing up. Here's the code I have implemented: HTML <div ng-app="myApp" ng-controller="custom ...

What is the process for updating the internal TypeScript version in VS Code?

When using VS Code, I noticed it comes with its own TypeScript version: Is there a way to update this? The current version is 4.9.3. ...

What are the steps to ensure a form does not trigger the action URL and instead only prints the data upon submission

Currently, I am working on creating a form that will submit without opening the action URL when a button is clicked. Additionally, after submission, I want to display a message and clear the form. Can anyone guide me on how to achieve this? <form id="c ...

What is the best way to retrieve the data stored in a TD element within a TR row in an HTML table?

How can I retrieve the value of a clicked table cell? https://i.stack.imgur.com/HfXBK.png <table id="table" class="table" style="margin-right: auto; margin-left: auto" > <thead> <tr> <th>Request Number</th> ...

The duration spent on a website using AJAX technology

We conducted an online survey and need to accurately calculate the time spent by participants. After using JavaScript and PHP, we found that the calculated time is not completely accurate. The original script was sending server requests every 5 seconds to ...

What is the procedure for accessing a namespace when declaring it globally?

Website Project Background Currently, I am working on a simple website where users can update their pictures. To achieve this functionality, I am utilizing the Multer library along with Express in Typescript. Encountered Issue I am facing a challenge re ...

What are the best strategies for creating HTML website designs that are both scalable, adaptable, and versatile?

As a beginner in HTML website design, I have recently started using HTML, CSS, jQuery, and JavaScript for designing websites. After creating a site with almost forty webpages, the client requirements are changing, requiring changes to be made across all ...

Should the header include individual CSS and JS files, or should all code be contained within a single CSS and JS file?

As I work on optimizing my website, I find myself juggling multiple plugins that include jQuery plugins with CSS along with my own JavaScript code. Currently, the CSS is spread across separate files for each plugin I have downloaded. When needed on a page ...

Mastering React children: A guide to correctly defining TypeScript types

I'm having trouble defining the children prop in TypeScript for a small React Component where the child is a function. class ClickOutside extends React.PureComponent<Props, {}> { render() { const { children } = this.props; return chi ...

Troubleshooting TypeScript in Visual Studio Code

Currently, I'm attempting to troubleshoot the TypeScript code below using Visual Studio Code: class Student { fullname : string; constructor(public firstname, public middleinitial, public lastname) { this.fullname = firstname + " " + ...

Change the height of textarea dynamically using jQuery

I am trying to create a comment box similar to Facebook's, where it resizes as text fills it using Expanding Text Areas Made Elegant This is how my view looks: <div class='expandingArea'> <pre><span></span></ ...

What is the best way to set up TSLint to apply specific rules with one line and different rules with another line

There is a unique method in which I can specify the code to format, such as forcing the else statement to be on the same line as the ending brace of an if statement. "one-line": [ true, "check-open-brace", "check-catch", "check-else", "check-fin ...

Selenium and JavaScript integration for opening new browser tabs

Hello there, I am looking to open new tests ('it' method) in new tabs and currently trying this approach: driver = new Builder().forBrowser('chrome').build(); beforeEach(() => { // driver.manage().window().open('url') ...

Is there a workaround for the issue of the NodeJS Web Cryptography API require() being undefined in an unsecure origin (Heroku App)?

My goal is to implement the experimental Web cryptography API (SubtleCrypto) on my Node.js server hosted on Herokuapp. The aim is to encrypt data from a fetch request sent from gitpages to herokuapp, concealing sensitive information from the browser consol ...