Skip to content

Error "'this' implicitly has type 'any'" when used .bind() #19639

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

Open
tenorok opened this issue Nov 1, 2017 · 10 comments
Open

Error "'this' implicitly has type 'any'" when used .bind() #19639

tenorok opened this issue Nov 1, 2017 · 10 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Domain: JavaScript The issue relates to JavaScript specifically Suggestion An idea for TypeScript

Comments

@tenorok
Copy link

tenorok commented Nov 1, 2017

› 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.
@ghost ghost added the Suggestion An idea for TypeScript label Nov 1, 2017
@ghost
Copy link

ghost commented Nov 1, 2017

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.

@mhegazy mhegazy added Salsa Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature labels Nov 1, 2017
@tenorok
Copy link
Author

tenorok commented Dec 7, 2017

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

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

@ghost
Copy link

ghost commented Dec 7, 2017

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

@JacobWeisenburger
Copy link

How do I fix this error?

image

@ghost
Copy link

ghost commented Aug 14, 2018

@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.

@JacobWeisenburger
Copy link

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

@weswigham weswigham added Domain: JavaScript The issue relates to JavaScript specifically and removed Domain: JavaScript The issue relates to JavaScript specifically Salsa labels Nov 29, 2018
@cScarlson
Copy link

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.

@neotan
Copy link

neotan commented Feb 25, 2020

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. */

@furkanmustafa
Copy link

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.

That is certainly a strong point of JavaScript. But also a strong concern point for some. If you wish to leverage those powers you have in JavaScript, then TypeScript is definitely not a good match for your needs. JavaScript is.

TypeScript is specificly for restricting what you can do with JavaScript.


I also got blocked by this limitation, and I had to go with @neotan 's suggestion. It worked for my need.

My use case is a (generic) debounce function, where it needs to hold a reference to this from the last invocation. To be able to make it a library function, I cannot annotate this used there.

I would appreciate if there is a way around this without disabling this check completely. Although I couldn't think of any easy way of this being possible.

@xgqfrms
Copy link

xgqfrms commented Feb 22, 2023

my solution

fix: TypeScript & ES5 function this error, 'this' implicitly has type 'any'

const nums = [1, 2, 3];
nums.myForEach(function(a, b, c, thisObj) {
  console.log(`a, b, c =`, a, b, c);
  console.log(`thisObj =`, thisObj);
  console.log(`this = `, this);
});

image

✅ just add this: any as the ES5 function's first argument.

const nums = [1, 2, 3];
nums.myForEach(function(this: any, a, b, c, thisObj) {
  // A 'this' parameter must be the first parameter.ts(2680) ✅
  console.log(`a, b, c =`, a, b, c);
  console.log(`thisObj =`, thisObj);
  console.log(`this = `, this);
});

image

test ✅

image

https://www.typescriptlang.org/play?#code/PQKhAIAEBcE8AcCm4DeBZWB5ARgKwL7gjABQAxgPYB2AztOBeALyonjvgBmFFAXFwFcqZaAEtqACgCUrDnPATOQkeKoToAC1E1+AQyqwZKNvNOVaFADaIAdJYoBzdVppSA3OGDBwgUHITp-BtsUSoAE2dtKSlpN39wfBJ8WJIQ6EQAJ05dMmQMHFxZDm4KCJ1UcF1+KgEAW2wM+Kl+ADcKUVDY-CA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Domain: JavaScript The issue relates to JavaScript specifically Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

8 participants