Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing private method with this argument specifier #17694

Closed
unional opened this issue Aug 9, 2017 · 6 comments
Closed

Accessing private method with this argument specifier #17694

unional opened this issue Aug 9, 2017 · 6 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@unional
Copy link
Contributor

unional commented Aug 9, 2017

tsc 2.4.1

const keyHandlers = {
  'ArrowDown': function (this: SomeComponent, $event) {
    // error on accessing private method.
    // `this` does not have method private `handleArrowDown`
    this.handleArrowDown($event);
  }
}

export class SomeComponent {
  onKeyDown($event) {
    if (typeof keyHandlers[$event.code] === 'function') {
      keyHandlers[$event.code].call(this, $event);
    }
  }
  private handleArrowDown(_event) {
    // ...
  }
}

Since the ArrowDown function takes the scope of this as SomeComponent, it is part of the class and should be able to access the private methods.

Origin: #9448 (comment)

@DorianGrey
Copy link

Suppose there is a misunderstanding here - the this: SomeComponent is just a definition, it does not affect the real (runtime) type, nor any scoping. How should it do so? The moment you're defining your function, there is no instance to bind to. Besides, that's why the arrow approach in the linked issue did not work as expected.

If you want the example above to work correctly, the most simple solution would be to use .call.
Turn

keyHandlers[$event.code]($event);

into:

keyHandlers[$event.code].call(this, $event);

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Aug 9, 2017
@unional
Copy link
Contributor Author

unional commented Aug 9, 2017

it is not about runtime. It is about the need of a special treatment of this type parameter to receive a type that includes the private functions. So that:

  • The said function can access the private methods/property of the class
  • The class can mark those private methods as used, avoiding noUnusedLocals error.

EDIT: @DorianGrey and yes, you are correct in pointing out the code doesn't work. I have updated the code snippet.

@DorianGrey
Copy link

it is not about runtime

Of course it is - you will always need a particular instance to bind the called function to, either explicit or implicit.

The said function can access the private methods/property of the class

Can you elaborate the benefit of this?
In the example above, I don't see a real benefit of externalizing the keyHandlers property - you will always have to provide the particular class instance, and you're calling a method of it. That code might save some bytes for not being stored in each instance of that class, but also makes it less clear what you're trying to achieve.
Besides, if I get that correctly, you want an external function to access private methods of a class - that contradicts the purpose of private methods. Even if that function has a this pointing to the particular instance, it is still not part of its prototype and thus outside the class definition. The explicitly typed this does not have a special role under these circumstances - just the same role as every other function parameter. Otherwise, it would be possible to access any private function of a class without any warning or error just by defining a function taking an instance of it via this and using .call on that function. I don't think that's the purpose of private.

@unional
Copy link
Contributor Author

unional commented Aug 9, 2017

Mixins

It is not "any" function. By specifically declaring the this argument, the author is telling the compiler his/her intent. It is an explicit declaration and the compiler should support that.

@RyanCavanaugh
Copy link
Member

The direction of causality is "Being inside the class gives you access to privates and a this of the class type", not "Having a this of the class type gives you access to privates". Buying a Wells Fargo nametag off eBay does not let me walk into the bank vault.

It's really not clear why getting some object passed to you via this should turn off all accessibility checking. private means "Only visible within the class body" (which some people don't even consider private enough!). The class itself defines how its private members can be accessed.

@mhegazy
Copy link
Contributor

mhegazy commented Aug 24, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants