Strategies for incorporating 'this' into a versatile method function

I'm struggling with the correct terminology for this issue, so I apologize if my title is not accurate. When attempting to utilize 'this' within a method, I am encountering an issue where it returns as 'undefined' during execution of the code.

My goal is to iterate through each 'api' and invoke it, allowing me to then manipulate the outcome. Each API may have distinct parameter data.

enum APIPermissions{ HIGH, LOW };
class Api{
  baseurl: string;
  constructor(admin: boolean){
    if(admin){
      this.baseurl = 'localhost';
    }else{
      this.baseurl = 'admin.localhost'
    }
  }

  api1(param1: string){
    return this.baseurl+'/api1 data';
  }

  api2(param1: string, param2: string){
    return this.baseurl+'/api2 data';
  }

  api3(json: any){
    return this.baseurl+'/api3 data';
  }
}
const api = new Api(true);
const data = [
{
    func: api.api1,
    params: ['test1'],
    permissions: [APIPermissions.LOW]
},
{
    func: api.api2,
    params: ['test1', 'test2'],
    permissions: [APIPermissions.HIGH]
}
]
  
for(const d of data){
    const result = d.func('a','b'); // d.params doesn't work
    console.log(result);
    // Check result and do something
}

The current output is: "undefined/api1 data" "undefined/api2 data"

However, I anticipate receiving "admin.localhost/api1 data". I reviewed the Typescript documentation but found the provided example to be confusing. Additionally, I am unsure how to correctly handle the part of d.func() that requires 2 parameters. Any assistance on resolving these issues would be greatly appreciated.

Answer №1

Compared to other programming languages, Javascript offers a higher level of dynamism. When extracting a function reference from an object, it is retrieved as just the function without any context attached.

To rectify this issue, it is important to explicitly bind the functions to an object instance. This solution can be implemented as follows:

const data = [
  {
    func: api.api1.bind(api),  
    params: ['test1'],
    permissions: [APIPermissions.LOW],
  },
  {
    func: api.api2.bind(api),   
    params: ['test1', 'test2'],
    permissions: [APIPermissions.HIGH],
  },
];

For further information on this topic, you may refer to this article discussing the concept of 'this is not bound'.

Answer №2

I encountered an issue where the 'this' of a method is returning 'undefined' while executing the code.

After extracting api1, api2, and api3 and storing them in an array of objects (data), they lose their context (this). This causes this.baseurl inside api1 or api2 to become undefined when calling d.func('a', 'b'), as this no longer points to the instance of Api.

To resolve this, utilize arrow functions (() => {}) for api1, api2, and api3. Arrow functions bind 'this' lexically, inheriting the context from their surrounding scope.

enum APIPermissions { HIGH, LOW };

class Api {
    baseurl: string;

    constructor(admin: boolean) {
        if (admin) {
            this.baseurl = 'localhost';
        } else {
            this.baseurl = 'admin.localhost';
        }
    }

    api1 = (param1: string) => {
        return this.baseurl + '/api1 data';
    }

    api2 = (param1: string, param2: string) => {
        return this.baseurl + '/api2 data';
    }

    api3 = (json: any) => {
        return this.baseurl + '/api3 data';
    }
}

const api = new Api(true);

const data = [
    {
        func: api.api1,
        params: ['test1'],
        permissions: [APIPermissions.LOW]
    },
    {
        func: api.api2,
        params: ['test1', 'test2'],
        permissions: [APIPermissions.HIGH]
    }
]

for (const d of data) {
    const result = d.func(...d.params); // Spread the parameters
    console.log(result);
    // Check result and do something
}

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

The 'ngModel' property cannot be bound to a 'textarea' element because it is not recognized as a valid property

When I run Karma with Jasmine tests, I encounter the following error message: The issue is that 'ngModel' cannot be bound since it is not recognized as a property of 'textarea'. Even though I have imported FormsModule into my app.modu ...

Utilize Promise.race() in Playwright Typescript to anticipate the appearance of one of two locators

Recently, I've delved into the world of Typescript while exploring Playwright for Test Automation. There's a scenario where two elements - Validated and Failed - can appear after some loading. In Selenium, my go-to method is to use WebDriverWait ...

What is the process of converting the new syntax of SomeFunction() to TypeScript?

When I try to convert a basic JS file to TS while having implicit "any" disabled, I encounter the following error: Error TS7009: When attempting to create a new expression without a constructor signature, it implicitly defaults to an 'any' typ ...

Access the properties of the encapsulated component in Vue 3, allowing for IDE autocomplete support

I have a vue3 component named MyButton which acts as a wrapper for the vuetify v-btn component. I am trying to figure out a way to make MyButton props inherit all of the props that v-btn has and also enable autocomplete feature in IntelliJ or VSCode. Is it ...

Emphasize a Row Based on a Certain Criteria

One of the challenges I am facing is how to emphasize a specific row in a table based on certain conditions. Currently, I am utilizing Jqxgrid and have made some modifications in the front-end to achieve the highlighting effect: TypeScript: carsDataAgain ...

The references to the differential loading script in index.html vary between running ng serve versus ng build

After the upgrade to Angular 8, I encountered a problem where ng build was generating an index.html file that supported differential loading. However, when using ng serve, it produced a different index.html with references to only some 'es5' scri ...

React: Dealing with unsuccessful imports

Whenever a device loses internet connection, my app crashes due to an imported component that relies on Google Maps. To address this issue and prevent the app from showing a blank screen, I want to intercept the failed Google Maps import and display an err ...

What's the reason behind the absence of the bar chart in this presentation?

I need help making a bar chart using d3 and Angular(in VSCode). The x-axis doesn't seem to work properly. Can anyone assist me with this issue? Currently, only the y-axis is displaying without any additional response. I've been stuck on this prob ...

The term 'string' is typically employed as a data type, yet in this instance it is being utilized as an actual value

Just started working with TypeScript and encountered an issue while trying to set the state. Encountered this error message: 'string' is a type and cannot be used as a value here. const state = reactive({ user: { uid: "", ...

What improvements can I make to enhance my method?

I have a block of code that I'm looking to clean up and streamline for better efficiency. My main goal is to remove the multiple return statements within the method. Any suggestions on how I might refactor this code? Are there any design patterns th ...

Tips for creating a seamless merge from background color to a pristine white hue

Seeking a seamless transition from the background color to white at the top and bottom of the box, similar to the example screenshot. Current look: The top and bottom of the box are filled with the background color until the edge https://i.stack.imgur.com ...

Having trouble retrieving the JSON data from the getNutrition() service method using a post request to the Nutritionix API. Just started exploring APIs and using Angular

When attempting to contact the service, this.food is recognized as a string import { Component, OnInit } from '@angular/core'; import { ClientService } from '../../services/client.service'; import { Client } from '../../models/Cli ...

Avoid accessing invariant variables when mocking: __extends

I'm currently in the process of converting a collection of react components from JavaScript to TypeScript, and I've encountered an issue with jest.mock(). Before: "react": "^15.6.1" "jest": "20.0.4" "enzyme": "^2.9.1" CustomDate.js ... import ...

Tips for stopping </p> from breaking the line

<p>Available: </p><p style={{color:'green'}}>{props.active_count}</p><p>Unavailable: </p><p style={{color:'red'}}>{props.inactive_count}</p> https://i.sstatic.net/NQo5e.png I want the ou ...

Adding a new document to an existing collection with an array field in MongoDB

Having an issue with adding a new chapter to my var array. Here is the code snippet in question: array.push({ chapter: [ { id: 2, title: 'adsf', content: &ap ...

Issue: Loading ES Module in MikroOrm and Typescript requires the use of import statement

My attempt to set up a mikrorm configuration for my postgres DB is hitting a snag when I try to run my run-dev script. The issue stems from an ESM compilation error: > yarn dev Error: Must use import to load ES Module: C:\Users\Itay&b ...

Tips for incorporating buttons into columns on ng2-table within Angular 2

I am in need of a table with an edit button in every column using ng2. However, I have encountered an issue placing the buttons at the end of each column. Here is my HTML code: <ng-table [config]="config.sorting" (tableChanged)="onChangeTable(co ...

What steps should I follow to create a versatile table component?

Can you please advise me on how to create generic data in a table using Typescript? I encountered this error message while trying to useTable({ at line data The error states: Type 'T[]' is not assignable to type 'readonly object[]'. ...

Guide to Setting Up "Remember Me" Login for Users in Angular

I am having trouble setting the 'Remember Me' option on my Login page. I tried using localstorage session but it seems like something is missing in the service file that's causing it not to respond properly. I attempted to follow a guide on ...

The parameter of type 'void' cannot be assigned to the parameter of type 'PathParams'

Established the route handler and encountered an issue while integrating it into my route. import {Application, NextFunction} from 'express'; import {container} from 'tsyringe'; const routeConstantsArray = { }; const constants: any ...