Typescript: Error "'this' implicitly has type 'any'" when used .bind()

Created on 1 Nov 2017  ·  8Comments  ·  Source: microsoft/TypeScript

› tsc --version
Version 2.7.0-dev.20171020

Code

tsconfig.json:

{
    "compilerOptions": {
        "allowJs": true,
        "checkJs": true,
        "noEmit": true,
        "strict": true
    },
    "files": [
        "index.d.ts",
        "index.js"
    ]
}

index.js:

/** @type {MyObj} */
const o = {
    foo: function() {
        (function() {
            console.log(this); // <- Unexpected error here.
        }.bind(this))();
    }
};

index.d.ts:

interface MyObj {
    foo(this: { a: number }): void;
}

How it looks in the editor:

Context of foo() is defined:
1

But context passed to the nested function is lost:
4

Expected behavior:

There should not be error, because this explicitly specified by .bind().

Actual behavior:

› tsc
index.js(5,25): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
Awaiting More Feedback JavaScript Suggestion

Most helpful comment

I simply tested noImplicitThis: false in TS playground, it seems work

// tsconfig.js

     "noImplicitThis": false,                /* Raise error on 'this' expressions with an implied 'any' type. */

All 8 comments

It's possible that we could detect this pattern like we detect IIFEs.
A workaround for now might be to use const that = this; instead if your runtime doesn't yet support arrow functions.

The same situations with context in loops like forEach():

/** @type {MyObj} */
const o = {
    foo: function() {
        [].forEach(function() {
            console.log(this); // <- Unexpected error here.
        }, this);
    }
};

Support for that was removed in #16223 for performance reasons.

How do I fix this error?

image

@offg777 That depends on the enclosing scope. Where do you expect this to come from? I assume this code isn't in a class (or this would have a type). If in a function you need to add a this: SomeType parameter to the front of the function's parameter list.

I think I understand now, I'm new to React. Thanks for the clarification.

This has got to be a bug. I can copy and paste insurmountable different, fully-tested functions & function-constructors into a TS file only to have a ton of work ahead of me just to satisfy TS. That's not necessarily nonsensical, but if TS exists because its intention is to be compiled to JS, then why should it matter if this is type any? Moreover, it tells me "'this' implicitly has type 'any' because it does not have a type annotation.ts(2683)"... Excuse me, isn't it the JS-Engine's job to "annotate" this??? Isn't that what this whole Call-Site thing is all about in JavaScript? You know, the one that has worked gracefully for decades? That's the whole point of this in JavaScript! So now a function must always know what it's Call-Site is... hmmm... Great, but I don't think that makes one lick of sense. If you think I should be the one annotating what this is, you clearly missed something central and critical to the language you're compiling to. What's worse, it prevents you from doing powerful things like:

function Methods() {
    ...
    this.method = (...) => {...};
    ...
    return this;
}
var $ = Methods.call(function jQuery(...) {...});
$(...).method(...);

I feel like this whole 'this' implicitly has type 'any' because it does not have a type annotation.ts(2683) thing is so obtrusive, blatantly misses the concept of this in JS, and is so frequently annoying that it should just be removed from TS -- or AT LEAST configurable in the tsconfig.json.

Is there a Type Declaration workaround for this problem? I need to be able to use Function Constructors at times. At the moment, function f(x) { this } and new (function () { return this; })() is unacceptable to TS -- and that is plain silly.

I simply tested noImplicitThis: false in TS playground, it seems work

// tsconfig.js

     "noImplicitThis": false,                /* Raise error on 'this' expressions with an implied 'any' type. */

Was this page helpful?
0 / 5 - 0 ratings