Skip to content

Suggestion: when compiling with noImplicityAny make 'this' have type '{}' where it previously had type 'any' #1740

Closed
@danielearwicker

Description

@danielearwicker

This would be a breaking change, so might need to be a separate flag. However I suspect anyone using noImplicitAny would switch on that flag, so maybe it should just be normal behaviour for noImplicitAny.

If inside a class method foo I write:

foo() {
    $.get('/blah', blah => this.blah = blah);
}

The lambda correctly preserves the type of this to be the surrounding class, and so my class better have a property blah that is of the right type or the compiler will complain. All good.

If instead I write:

foo() {
    $.get('/blah', function() { this.blah = blah; });
}

Now this no longer refers to the class object, so it no longer works. This is fine - function has different behaviour.

The problem is that this has been given the type any.

You might argue that I asked the compile to do that by saying function() {... instead of using a lambda, so this wasn't an implicit any, as such.

Yes, in that example the problem is easy to spot thanks to the function keyword. But how about:

foo() {
    this.mouseEvents = {
        down() {
            this.mouseDown = true;
        },
        up() {
            this.mouseDown = false;
        }
    }
}

No function keywords, because I'm using ES6's nice abbreviation for an object literal with functions. Inside down(), this is again not the surrounding object but is the new object I'm assigning to this.mouseEvents. Sometimes that's what I want, but in this case it's not. The problem is again that this is of type any so the compiler checks nothing.

So the suggestion is to give this the type {} in these circumstances. In the (hopefully rare) cases where I genuinely do want to smuggle information into a function via untyped this, I will need to do my own explicit declaration at the start of the function:

var extraInfo: any = this;

But if it's a mistake (most cases), I'll find out when I try to access my class's properties/methods on {}.

For bonus points, in the object literal example, the type of this could be the type of the object literal (that's what it is at runtime). But I guess that might raise circularity difficulties. The core problem here is the implicit introduction of this: any.

Metadata

Metadata

Assignees

No one assigned

    Labels

    SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions