Accessing class properties in a function

Topics: General
Jul 9, 2013 at 9:20 AM
Edited Jul 9, 2013 at 11:19 AM
How are we supposed to do this? See this simple Knockout/TypeScript sample:
<i class="icon-edit" data-bind="click: $parent.GetEditForm"></i>
export class Foo
{
    public ID: KnockoutObservable<Number>;
}

export class FooEditor
{
    private get me() { return this; }

    public Items: KnockoutObservableArray<Foo>;

    public GetEditForm(item: Foo, event)
    {
        console.log(self);
        console.log(me); // Could not find symbol 'me'.
        console.log(this.me);
        console.log(this);
    }
}
  • self refers to Window, making a class property with this name has no use.
  • me doesn't compile.
  • this.me refers to the instance of FooEditor according to TypeScript, but in reality it refers to the instance of Foo (making this output undefined) so type safety is non-existent at this point. I can no longer trust the compiler or IntelliSense!
  • this has the same remark as this.me
Arrow expressions are not an option, unless you can show me how these can be used with overloading.
public Foo(item: Bar): void;
public Foo(item: Baz): void;
public Foo(item: any)
{

}
Jul 9, 2013 at 12:29 PM
Edited Jul 9, 2013 at 12:29 PM
I've found various workarounds for this issue, using arrow functions and proxy functions. I've settled for a combination.
constructor()
{
    this.GetEditForm = (item: any) => {
        this.GetEditFormProxy.apply(this, arguments);
}

public GetEditForm(item: Bar): void;
public GetEditForm(item: Baz): void;
public GetEditForm(item: any) { }
private GetEditFormProxy(item: any
{
    console.log(this);
}
Jul 9, 2013 at 1:28 PM
I don't know what goes on in Knockout these days, but using
class FooEditor {
  getEditForm;

  constructor() {
    this.getEditForm = this._getEditForm.bind(this);
  }

  private _getEditForm(item: any) {
    console.log(this);
  }
}
(Of course, in AngularJS you can bind directly to objects from your markup, rendering all this sort of thing moot. Just sayin'.)
Jul 9, 2013 at 1:40 PM
@markrendle I'm not really sure what you're saying? I am binding from my markup.
The code you posted is similar to mine, except you use bind instead of apply. Perhaps you didn't see my reply?
Jul 9, 2013 at 2:10 PM
Similar, yes, but shorter and more to the point.

In AngularJS, I add my controller class to the $scope, i.e. $scope["c"] = this;. In my bindings, I can use something like ng-click="c.save()" and the method is called as a method, as opposed to being detached from the object and called as a function (which is what is causing you problems).