1
\$\begingroup\$

This is a interview practice question from BFE.dev.

Currying is a useful technique used in JavaScript applications.

Please implement a curry() function, which accepts a function and return a curried one.

The solution is pretty simple, but when implementing it with TypeScript the compiler will throw a warning about my usage of this.

// This is a JavaScript coding problem from BFE.dev 
function curry(fn: (...args: any[]) => any): (...args: any[]) => any {
  return function curried(...args: any[]): any {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return curried.bind(this, ...args);
    }
  }
}

The warning:

'this' implicitly has type 'any' because it does not have a type annotation.

So then I have two questions:

  1. What should this be in this context?
  2. How can I type this to be correct based on the answer to #1?

For #1 I looked at Arnav Aggarwal's "Simple Rules to this in JavaScript."

  1. If the new keyword is used when calling the function, this inside the function is a brand new object.
  2. If apply, call, or bind are used to call/create a function, this inside the function is the object that is passed in as the argument.
  3. If a function is called as a method, such as obj.method() — this is the object that the function is a property of.
  4. If a function is invoked as a free function invocation, meaning it was invoked without any of the conditions present above, this is the global object. In a browser, it is the window object. If in strict mode ('use strict'), this will be undefined instead of the global object.
  5. If multiple of the above rules apply, the rule that is higher wins and will set the this value.
  6. If the function is an ES2015 arrow function, it ignores all the rules above and receives the this value of its surrounding scope at the time it is created.

I'm pretty sure #1 can be eliminated (probably?), but #2, #3, and #4 all seem like they could be true at runtime. So then, how can I type this properly?

\$\endgroup\$
1
  • \$\begingroup\$ I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to edit and give it a different title if there is something more appropriate. \$\endgroup\$ Oct 2, 2023 at 21:41

1 Answer 1

2
\$\begingroup\$

You can annotate this in the following way:

function curry(fn: (...args: any[]) => any): (this: CallableFunction, ...args: any[]) => any {
...

In your context, the code is calling apply and bind on this. In order to do that this may be typed as a CallableFunction.

\$\endgroup\$
3
  • \$\begingroup\$ @SᴀᴍOnᴇᴌᴀ I don't really see why this was closed. The code runs exactly as intended, but gets TypeScript warnings. TypeScript has (mostly) nothing to do with actual runtime behavior. \$\endgroup\$ Oct 2, 2023 at 20:46
  • \$\begingroup\$ I apologize- it wasn't obvious that it was just a warning. After going through CR meta I realize in general code with warnings are acceptable and I have updated your question to make it clear that it is a warning instead of an error. \$\endgroup\$ Oct 2, 2023 at 21:33
  • \$\begingroup\$ @SᴀᴍOnᴇᴌᴀ Thank you! \$\endgroup\$ Oct 2, 2023 at 22:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.