0

I have a class:

const helper = function(val){
   console.log(this.a);
   console.log(this.b);
   this.bar();
};

export class Foo {

 public b = '45'
 private a = 15;

 bar(){

 }

 myMethod(){
    return helper.apply(this,arguments);
 }

}

the problem is, in the helper function, it doesn't know what the context is (what the value of 'this' is).

Is there a way for me to tell typescript that the value for this in the helper function is an instance of Foo?

(the reason I use the helper function is to create true private methods).

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • Here's a StackBlitz: https://stackblitz.com/edit/angular-dzmfb1 (this is an Angular one but I'm just using main.ts as a typescript file here). Check the browser console, it seems to behave like you want it to. – Jeto Mar 17 '18 at 00:35
  • that's working at runtime (naturally) ... but at compile time, TS doesn't know what `this` is (it cannot know because it's dynamic, unless you tell TS that it's always one kind of type) – Alexander Mills Mar 17 '18 at 00:37
  • 1
    What about `let self: Foo = this as Foo;` and then use `self`? Could also replace `this` with `(this as Foo)` everytime you use it. – Jeto Mar 17 '18 at 00:41
  • that might work idk, if you think it works, add an answer I will upvote – Alexander Mills Mar 17 '18 at 00:42
  • Just did. Not 100% sure this is what you meant but this should let your compiler/IDE know you're working with a `Foo` instance. – Jeto Mar 17 '18 at 00:45
  • Why not `const helper = function(t: Foo, val){ console.log(t.a); }`? It would be statically typed. – zerkms Mar 17 '18 at 01:14
  • 1
    @zerkms I tried that actually and it said private methods/members of `t` could not be accessed by `t` even though it was declared as `Foo`, lame! – Alexander Mills Mar 17 '18 at 01:14
  • 1
    Oh right. So you want a private method that is not available from the JS runtime, I see. – zerkms Mar 17 '18 at 01:15

2 Answers2

1

Try adding this on top of your helper function:

let self: Foo = this as Foo;
// use self instead of this below

Alternatively, you could replace all instances of this in it with (this as Foo).

Jeto
  • 14,596
  • 2
  • 32
  • 46
1

You can declare the type of this for any function by adding an extra parameter named this. The this parameter will not be emitted to Javascript, it will be just for the benefit of the compiler to be able to type check your code:

const helper = function(this: Foo, val: number){
    console.log(this.a); /// error a is private
    console.log(this.b);
    this.bar();
 };

This will not however break encapsulation, you will still not be able to access private properties from outside the class, so unless you create the function inside the class it will still give an error as above. For functions defined inside the class it will not give errors:

export class Foo {

    public b = '45'
    private a = 15;
    bar() { }
    createHelper() {
        return function (this: Foo, val: number) {
            console.log(this.a);
            console.log(this.b);
            this.bar();
        };
    }

    myMethod() {
        return this.createHelper().apply(this, arguments);
    }

}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357