Is there a way to get this reducer function to work within a TypeScript class?

For the first advent of code challenge this year, I decided to experiment with reducers. The following code worked perfectly:

export default class CalorieCounter {
  public static calculateMaxInventoryValue(elfInventories: number[][]): number {
    const sumInventoriesReducer = (
      acc: number[],
      element: number[]
    ): number[] => [...acc, this.sumCalories(element)];

    return Math.max(...elfInventories.reduce(sumInventoriesReducer, []));
  }

  private static sumCalories(inventory: number[]): number {
    return inventory.reduce((a: number, b: number) => a + b, 0);
  }
}

Later on, I attempted to separate the sumInventoriesReducer into its own private function within the same class. Unfortunately, this new code did not work as expected:

export default class CalorieCounter {
  public static calculateMaxInventoryValue(elfInventories: number[][]): number {
    return Math.max(...elfInventories.reduce(this.sumInventoriesReducer, []));
  }

  private static sumInventoriesReducer(
    acc: number[],
    element: number[]
  ): number[] {
    return [...acc, this.sumCalories(element)];
  }

  private static sumCalories(inventory: number[]): number {
    return inventory.reduce((a: number, b: number) => a + b, 0);
  }
}

The logic remains the same in both versions, the only change being the extraction of the reducer into a private function (the static keyword is not the issue, as I tried without it and encountered the same error).

The specific error message that appeared is:

 TypeError: Cannot read property 'sumCalories' of undefined

      20 |     element: number[]
      21 |   ): number[] {
    > 22 |     return [...acc, this.sumCalories(element)];
         |                          ^
      23 |   }
      24 |
      25 |   private static sumCalories(inventory: number[]): number {

I am striving to approach this problem from an object-oriented perspective, even though I understand that reducers are typically associated with functional programming. Is there anyone who can offer guidance on how to make this private class function work properly?

Answer №1

One issue is that you're attempting to access an instance property (which only exists after the constructor() is called) in a static method (which only exists on the class and not on the prototype).

Once the constructor() method has been executed, the keyword this refers to the instance object. However, referencing this in a static method will result in an undefined variable because static methods do not require a constructor method.

export default class CalorieCounter {
  public static calculateMaxInventoryValue(elfInventories: number[][]): number {
    return Math.max(...elfInventories.reduce(this.sumInventoriesReducer, []));
  }

  private static sumInventoriesReducer(
    acc: number[],
    element: number[]
  ): number[] {
    return [...acc, this.sumCalories(element)]; // The issue lies here
  }

  private static sumCalories(inventory: number[]): number {
    return inventory.reduce((a: number, b: number) => a + b, 0);
  }
}

If you wish to maintain this structure, you can simply update that line as follows:

  • from: this.sumCalories(element)
  • to:
    CalorieCounter.sumCalories(element)
    By making this change, you are accessing the method directly from the class rather than an instance that does not exist.

The revised code would look like this:

export default class CalorieCounter {
  public static calculateMaxInventoryValue(elfInventories: number[][]): number {
    return Math.max(...elfInventories.reduce(this.sumInventoriesReducer, []));
  }

  private static sumInventoriesReducer(
    acc: number[],
    element: number[]
  ): number[] {
    return [...acc, CalorieCounter.sumCalories(element)]; // The issue lies here
  }

  private static sumCalories(inventory: number[]): number {
    return inventory.reduce((a: number, b: number) => a + b, 0);
  }
}

Similarly, the calculateMaxInventoryValue method is static but attempts to access an instance method. By correcting it, the code should be structured like this:

export default class CalorieCounter {
  public static calculateMaxInventoryValue(elfInventories: number[][]): number {
    return Math.max(...elfInventories.reduce(CalorieCounter.sumInventoriesReducer, []));
  }

  private static sumInventoriesReducer(
    acc: number[],
    element: number[]
  ): number[] {
    return [...acc, CalorieCounter.sumCalories(element)]; // The issue lies here
  }

  private static sumCalories(inventory: number[]): number {
    return inventory.reduce((a: number, b: number) => a + b, 0);
  }
}

Answer №2

The reason for this issue is that you have not flattened the output of this.sumCalories(element).

this.sumCalories(element) generates a number[], so in order to combine it with the current accumulator, you should flatten it using the spread operator.

To resolve this problem, try using

return [...acc, ...this.sumCalories(element)];
.

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

Easily transform checkboxes into images using jQuery with no need for external plugins

Is it possible to replace checkboxes with images without using jQuery plugins? I'm hoping to achieve this in just a few lines of code. Thank you. ...

Utilizing JSON data to generate an HTML webpage showcasing a collection of community districts through the power of JavaScript

As a beginner in javascript, I am working with a JSON file that contains an array of objects. Each object includes two properties: a borough and mappings. Mappings have two sub-properties called macro and neighborhoods. The macro represents a larger neighb ...

Adding a class to radio buttons and checkboxes in Angular when they are checked or selected without needing to trigger a change event

I am looking to implement ngClass based on whether an item is checked or not. Essentially, I want the user to visually see which items are selected through radio buttons or check-boxes by adding a class to them, allowing me to apply different CSS styles to ...

Sequelize.js: Using the Model.build method will create a new empty object

I am currently working with Sequelize.js (version 4.38.0) in conjunction with Typescript (version 3.0.3). Additionally, I have installed the package @types/sequelize at version 4.27.25. The issue I am facing involves the inability to transpile the followi ...

Using Regular Expression to verify the presence of numbers and spaces

Currently, I have implemented a regular expression that ensures my string contains 5 digits. While this regex works flawlessly, I now also require it to allow white spaces: both "123 45" and "12345" should meet the criteria. string.match(/^\d{5}$/g); ...

Exploring portfinder in Javascript: A guide to its usage

As a newcomer to Javascript, I am eager to figure out how to utilize the portfinder.getPort() function within one of my functions in order to generate a random port each time. The code snippet below showcases my current implementation: var portfinder = re ...

Embed your JavaScript code within the header tags of the WooCommerce order confirmation page

Seeking to enhance my thank you page with Google tracking script, I have developed code that successfully injects the tracker within the of the page, incorporating dynamic values. However, my goal is to embed it within the tags instead. function mv_goog ...

Exploring Firebase's Collection Retrieval through Vue.js

Trying to retrieve a specific collection from Firebase Firestore is giving me an error that I haven't been able to resolve yet. Below is the code snippet from my boot file: import { initializeApp } from "firebase/app"; import { getFirestore ...

Tips on including starting information into an angularjs application from the displayed HTML

I'm currently working on a complex AngularJs application that requires User Login. Once the user is authenticated, a page will be displayed to them and additional data will be loaded later. There are two methods for achieving this: XHR Fetch af ...

The padding on the button inside the v-card is not being applied as expected

I am facing an issue with the following code snippet: <v-card height="200"> <v-card-actions class="mb-0"> <v-btn flat color="orange">Share</v-btn> <v-btn flat color="orange">Explore</v-btn> & ...

How to preselect an item in a RadioGroup

We are facing a challenge in setting a default value automatically for a RadioGroup upon page load. Despite the documentation mentioning a defaultValue property (https://material-ui.com/api/radio-group/), it does not seem to work as expected. We experimen ...

When incorporating Vue as an npm package, a Vue 3 app may inadvertently clear the mounted element upon initialization

I have a straightforward Vue 3 application that is working perfectly fine when I include Vue as a script, as shown in the code snippet below. However, I need to integrate it with webpack by including it as an npm package. When I do this, the app loads but ...

Encountering Routing Issues in Express.js Following Passport.js Authentication

My authentication setup with Passport.js is pretty straightforward. After the user successfully authenticates, I redirect them to /work like this. app.post('/login', passport.authenticate('local', { successRedirect: '/ ...

Create a spinner control on an HTML webpage with the help of JavaScript

I am attempting to create a spinner control on my webpage, and I have tried the following code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.o ...

How can I achieve the quickest image loading speed with JavaScript?

If I have a large ecommerce website with 15,000 image elements that need to be added to the HTML, what is the best approach using JavaScript to optimize efficiency and enhance user experience? ...

Is there a way to access every item that includes a particular attribute and attribute term within the woocommerce-rest-api?

Struggling to retrieve products that have the "x-attribute" and "x-attribute-term" using Node.js with the WooCommerce REST API library from here. I've explored solutions on stackoverflow and other sites but none seem to work. Atte ...

Ways to store data in the localStorage directly from a server

I'm facing an issue - how can I store data in localStorage that was received from the server? Should I use localStorage.setItem for this purpose? And how do I handle storing an array in localStorage? Or am I missing something here? import { HttpCli ...

Transferring ipywidgets to a web platform

I've developed a Python program in Jupyter Notebook that leverages the interact function from the ipywidgets module. interact(my_func, filter_by=filter_by_list, format_type=format_dict.keys()) I am looking for a way to share this interactive widget ...

Operating with a multidimensional entity

I am aiming for an object structure like this: {"Red 1":53,"Blue 2":26,"Green 3":25} Based on the following example: I attempted to push data from within .each loop into the object. However, due to its multidimensional nature, I'm uncertain how to ...

Explain the concept of utilizing curried state handlers within a React and Typescript application

I am currently working on defining the function that will handle change events to update the state value accordingly. This is what I envision the implementation to look like: handleChange: ChangeHandler<State> = field => value => this.set ...