0

I have a project in Node JS and Typescript in which I am trying to share variables between classes within the same file.

This is the class I want to get the max variable from:

export class constUt {
    env: string;
    max: number;

    constructor() {
        this.env = 'dev';
        this.max = 100;
    }
}

This is the class I'm trying to pick up the max variable in:

export class callBack {

    private utilsCo = new constUt();

    call = function (err:any, csv:any) {
        console.log(`max constUt: ${this.utilsCo.max}`); //error

        if (err) throw err;
    }
}

My problem is that I don't know how to read the max variable inside the call function

menphis
  • 85
  • 1
  • 8

2 Answers2

1

The problem is not the sharing of the variable, but the way you have declared the function. You are declaring the function as a class variable which results in a function that is not necessarily bound to the class that is declaring it. In other words, TypeScript does not know what the context this refers to.

You can fix it in one of these ways:

  1. declare it as a class member
export class callBack {

    private utilsCo = new constUt();

    public call(err:any, csv:any) {
        console.log(`max constUt: ${this.utilsCo.max}`); 

        if (err) throw err;
    }
}
  1. Declare it as an arrow function (which will inherit the context from the class)
export class callBack {

    private utilsCo = new constUt();

    call = (err:any, csv:any) => {
        console.log(`max constUt: ${this.utilsCo.max}`); 

        if (err) throw err;
    }
}
  1. Explicitly set the context:
export class callBack {

    private utilsCo = new constUt();

    call = function (this: callBack, err:any, csv:any) => {
        console.log(`max constUt: ${this.utilsCo.max}`); 

        if (err) throw err;
    }
}

There's a subtle difference in each of these declarations.

1 is declared on the class prototype (with all the implications that has)

2 cannot have its context changed (though you probably don't want that in this case)

3 the context is statically typed so there's no runtime guarantees (same as (1) but unlike (2))

apokryfos
  • 38,771
  • 9
  • 70
  • 114
  • The third way is the only one that has worked for me but I have a problem, I am calling that function from another class in another file with the following code: ``import {callBack} from '../ utils / const.utils';`` and then to initialize it ``let caller = new callBack().call;``. The ``caller`` variable returns the complete ``call`` method to me, how do I make the method execute and return only the value of ``max``? – menphis Jun 09 '21 at 17:44
  • The same way you would execute a JavaScript method e.g. `let caller = (new callBack()).call()` – apokryfos Jun 10 '21 at 09:45
-1

I tried your code in stackblitz and it is working fine. Below I have added non typescript version of your code for understanding purpose.

You only need to add following two lines to get the output.

Tip: capitalize first letter of class name to distinguish it from other variables or class instances.

let callback = new CallBack();
    callback.call(null, {});
============================
Your typescript code with above two lines 
==============================

// constUt.ts
// ================================

export class constUt {
    env: string;
    max: number;

    constructor() {
        this.env = 'dev';
        this.max = 100;
    }
}


// callback.ts
// ================================

export class CallBack {

    private utilsCo = new constUt();
    
    call = (err:any, csv:any) => {
        console.log(`max constUt: ${this.utilsCo.max}`); // OUTPUT : max constUt: 100

        if (err) throw err;
    }
}

// Following two lines are added to view the expected output
// You need to create instance of your callback class and then call the call method with required parameters
// Pass the null value if you don't need to execute error block and not to throw error

let callback = new CallBack();
callback.call(null, {});

Working Example

class ConstUt {
    env;
    max;

    constructor() {
        this.env = 'dev';
        this.max = 100;
    }
}

class CallBack {

    utilsCo = new ConstUt();
    
    call = (err, csv) => {
        console.log(`max constUt: ${this.utilsCo.max}`); // OUTPUT : max constUt: 100

        if (err) throw err;
    }
}

// Following tow lines are added to view the expected output

let callback = new CallBack();
callback.call(null, {});

I hope this will be helpful.

Thanks, Jignesh Raval

Jignesh Raval
  • 587
  • 7
  • 15
  • This code that is what I have shows me an error in this: ``'this' implicitly has type 'any' because it does not have a type annotation.ts(2683) const.utils.ts(73, 24): An outer value of 'this' is shadowed by this container.``. This is line 73: ``call = function (err: any, csv: any) {`` – menphis Jun 09 '21 at 17:36
  • Hi @menphis, there is no line no 73 in your code which you have shared in this thread. But as per my understanding if you are getting error in binding the value of "this" then try ES6 arrow method to restore the context of "this". I hope that will resolve your issue. for example : ```call = (err:any, csv:any) => {console.log(`max constUt: ${this.utilsCo.max}`); if (err) throw err; }``` https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback/20279485#20279485 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions – Jignesh Raval Jun 10 '21 at 05:38