0

Using scalajs-jquery 0.8.0, under the following import assumptions:

import org.scalajs.jquery.{jQuery => $`, the following does not compile:
import dom.html.Element

The following code does not compile, which is my problem:

      $("").hover(((_this: Element, event: JQueryEventObject) => {
      }): js.ThisFunction)
type mismatch;
 found   : scala.scalajs.js.ThisFunction
 required: scala.scalajs.js.Function1[org.scalajs.jquery.JQueryEventObject,scala.scalajs.js.Any]

But the following does compile.

  $("").click(((_this: Element, event: JQueryEventObject) => {
  }): js.ThisFunction)

Since the methods click and hover have the same signature (and hence same implicits should apply), why does the first call not compile but the second call does? See JQuery.scala

Edit: Workaround: A workaround I found is to explicitely cast the function, so:

      $("").hover((((_this: Element, event: JQueryEventObject) => {
      }): js.ThisFunction).asInstanceOf[js.Function1[org.scalajs.jquery.JQueryEventObject,scala.scalajs.js.Any]])
Mikaël Mayer
  • 10,425
  • 6
  • 64
  • 101

1 Answers1

1

The reason the call to click works, is that there also exists an overload taking a simple js.Any (named eventData). For hover, this overload doesn't exist.

For a proper solution, 2 things are needed IMHO:

  1. An overload for hover (and click) that accept a js.ThisFunction1[Element, JQueryEventObject, js.Any]
  2. Changing your type ascription to js.ThisFunction1[Element, JQueryEventObject, js.Any] (removing it after 1. is fixed)

Let me give some more thorough explanation:

First point: Not every method that accepts a js.Function1[A, B] should accept a js.ThisFunction1[T, A, B], since it might not call the given function with a well defined this reference. The fact that we can't decide what T should be, already illustrates that.

Therefore, facades that accept do bind the this reference, should have overloads accepting a (properly typed) js.ThisFunction.

Second point: You are ascribing your js.Function2[Element, JQueryEventObject, js.Any] to a simple js.ThisFunction. Therefore, the compiler has no way of checking that the types of the actual arguments to your function match the ones of its formal parameters.

You will have to ascribe the full type to work around this. AFIK, there is no way to have the type inferencer handle that at this point in the Scala.js library. However, this could be a reasonable feature request.

There is an implicit conversion from scala.FunctionN to js.ThisFunction<N-1>, so as soon as there exists an overload for the method you need, you can get completely rid of any ascription or cast.

Solution: Currently this leaves you stuck with your workaround, since you need an external change in scalajs-jquery. Going forward, you could open change requests / PRs to scalajs-jquery.

gzm0
  • 14,752
  • 1
  • 36
  • 64
  • Just a side-note: jquery-facade, being more strongly typed, generally doesn't need any of the type ascriptions -- since it doesn't have all those js.Any's, the compiler can usually infer the function type correctly. That's less complete than scala-js-jquery, but if you'd like to explore that route instead, I'd be happy to add the hover functions... – Justin du Coeur Sep 23 '15 at 14:50