Reputation: 59994
Suppose I have this definition in Scala.js for the return type of a function of some library I'm using:
@native
trait Link extends Object {
val href: String = native
val title: String = native
}
What's the best, typesafe way, in Scala code, to define an object literal conforming to this? I thought the use(...).as[...]
trick would work:
val link = js.use(new {
val href = "value1"
val title = "value2"
}).as[Link]
But this yields the error:
AnyRef{val href: String; val title: String} does not export a getter href: String
Why?
I also tried this, and as expected it fails:
val link = js.use(js.Dynamic.literal(
href = cap(2),
title = cap(3)
)).as[Link]
gives
scala.scalajs.js.Object with scala.scalajs.js.Dynamic does not have a getter href: String
Finally, I also tried this:
val link = new Link {
override val href = "value1"
override val title = "value2"
}
and got
A Scala.js-defined JS class cannot directly extend a native JS trait
Right now, I'm doing this:
val link = js.Dynamic.literal(
href = "value1",
title = "value2"
).asInstanceOf[Link]
This works, but it's not checked by the compiler if I'm not mistaken.
Upvotes: 5
Views: 1101
Reputation: 22085
The library should declare Link
as @ScalaJSDefined
instead of @js.native
. That would allow you to do the third variant (the one with new Link { ... }
. I suggest you file a bug report for that library.
As a workaround, either do what you're doing with the .asInstanceOf[Link]
, or, if you want the js.use(x).as[T]
safety, use this:
@ScalaJSDefined
trait LinkImpl extends js.Object {
val href: String
val title: String
}
val link = js.use(new LinkImpl {
val href = "value1"
val title = "value2"
}).as[Link]
Upvotes: 7