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

What could be causing the ExcelJs plugin to malfunction in Internet Explorer 11?

My current setup involves Angular 9 and excelJs 4.1.1, which works perfectly in Chrome but throws an error in IE11 stating: "Invalid range in character set" in polyfills-es5.js Surprisingly, when I remove this dependency from package.json, everything func ...

issues with jasmine angularjs tests exhibiting erratic outcomes

During the execution of my unit tests, I often encounter a scenario where some random test(s) fail for a specific controller without any apparent reason. The error messages typically look like this: Expected spy exec to have been called with [ Object({}) ...

Having trouble getting a button's OnClick event to work with Bootstrap on iOS devices

Here is an example of the issue I'm experiencing: http://jsfiddle.net/d01sm5gL/2/ The onclick event functions correctly on desktop browsers, however when using iOS8, the event does not trigger. I have tried calling the function manually through the d ...

"Troubleshooting Why AJAX Update for CGridView is Not Functioning

I've encountered an issue with my CGridView grid where I receive an error every time I try to update it. Despite spending a lot of time trying to resolve this, I still haven't been able to figure out what's missing. Here's the code sni ...

What could be causing the shadowbox not to display in Internet Explorer?

I am currently working on fixing a shadowbox issue in Internet Explorer. The page where the shadowbox is located can be found at this link: Here is the HTML code: <div class="hero-image"> <a href="m/abc-gardening-australia-caroli ...

Ways to eliminate all attributes and their corresponding values within HTML tags

Hey there, I'm trying to strip away all the attribute values and styles from a tag in html Here's my Input: <div id="content"> <span id="span" data-span="a" aria-describedby="span">span</span> <p class="a b c" style=" ...

Guide to aligning a component in the middle of the screen - Angular

As I delve into my project using Angular, I find myself unsure about the best approach to rendering a component within the main component. Check out the repository: https://github.com/jrsbaum/crud-angular See the demo here: Login credentials: Email: [e ...

Which library does stackoverflow utilize to showcase errors (utilizing Bootstrap popover for error help-block)?

Currently, I am using bootstrap's has-error and help-block classes to display validation error messages in my form. However, I find the error message display in Stackoverflow's Ask Questions Form to be very appealing. Are they using a specific js ...

[deactivated]: Modify a property's value using a different component

One of the requirements for my button is that it should be disabled whenever the callToActionBtn property is true. match-component.html <button [disabled]="callToActionBtn" (click)="sendTask()>Send</button> match-component.ts public callToA ...

Menu with options labeled using IDs in FluentUI/react-northstar

I'm currently working on creating a dropdown menu using the FluentUI/react-northstar Dropdown component. The issue I'm facing is that the 'items' prop for this component only accepts a 'string[]' for the names to be displayed ...

Using jQuery to combine a variable with the image source in order to replace the image attribute

I am trying to create a script that will display a greeting message to the user based on their local time. I found a script on Stack Overflow, but I am struggling with updating the image source. When I try to replace the image source, I encounter the follo ...

Avoiding cheating in a JavaScript game

I am in the process of creating a JavaScript/JQuery game that resembles a classic brick breaker. The game includes features such as scoring, levels, and more. I have plans to add a leaderboard where users can submit their final scores. However, my concer ...

Separate every variable with a comma, excluding the final one, using jQuery

I've developed a script that automatically inserts checked checkboxes and radio options into the value() of an input field. var burgerName = meat + " with " + bread + " and " + onion + tomato + cheese + salad; $('#burger-name').val(burger ...

Submitting a form into a database with the help of AJAX within a looping structure

Trying to input values into the database using AJAX. The rows are generated in a loop from the database, with each row containing a button column. Clicking on the button submits the values to the database successfully. The issue is that it only inserts va ...

Is there a way to directly update the value of a nested object array using v-model in VUE?

Looking to update a value in JSON using v-model { class: "data.child", "myform.input1": [true, "<input1 value>"] } <input type="text" v-model="<what should be inserted here?>" > //update the value directly in my ...

Store the information from an AJAX post request in a div element into the browser

I've set up a datatable with a button that posts data into a div. Below is the HTML code I used: HTML : <div class="card-body"> <div class="overlay" id="kt_datatable_nodata"> <div class="o ...

React: maintaining referential equality across renders by creating closures with useCallback

I want to make sure the event handling function I create in a custom hook in React remains referentially equal across renders. Is it possible to achieve this using useCallback without specifying any variables it closes over in the dependencies list? Will o ...

Updating Angular components by consolidating multiple inputs and outputs into a unified configuration object

When I develop components, they often begin with numerous @Input and @Output properties. However, as I continue to add more properties, I find it beneficial to transition to utilizing a single config object as the input. For instance, consider a component ...

JavaScript throws an error when attempting to access an object's methods and attributes

Within my Angular.js module, I have defined an object like this: $scope.Stack = function () { this.top = null; this.size = 0; }; However, when I try to use the push method of this object, I encounter an error stating undefined: ...

"Encountering a problem with a missing object in jQuery when referencing

I'm encountering an issue with jQuery's $(this) object that's causing me to lose track of the this element in my code: $('.star').click(function (){ var id = $(this).parent().attr('id').split('rating')[ ...