在Scala.js中,如何最好地创建符合JS façade trait 的对象?

In Scala.js, how to best create an object conforming to a trait from a JS façade?

假设我在 Scala.js 中为我正在使用的某个库的 return 类型的函数定义了这个:

@native
trait Link extends Object {
  val href: String = native
  val title: String = native
}

在 Scala 代码中,什么是最好的、类型安全的方式来定义符合 this 的对象字面量?我认为 use(...).as[...] 技巧会奏效:

val link = js.use(new {
  val href = "value1"
  val title = "value2"
}).as[Link]

但这会产生错误:

AnyRef{val href: String; val title: String} does not export a getter href: String

为什么?

我也试过了,果然失败了:

val link = js.use(js.Dynamic.literal(
  href = cap(2),
  title = cap(3)
)).as[Link]

给予

scala.scalajs.js.Object with scala.scalajs.js.Dynamic does not have a getter href: String

最后,我也尝试了这个:

val link = new Link {
  override val href = "value1"
  override val title = "value2"
}

得到了

A Scala.js-defined JS class cannot directly extend a native JS trait

现在,我正在这样做:

val link = js.Dynamic.literal(
  href = "value1",
  title = "value2"
).asInstanceOf[Link]

这行得通,但如果我没记错的话,编译器不会检查它。

库应将 Link 声明为 @ScalaJSDefined 而不是 @js.native。这将允许您执行第三种变体(带有 new Link { ... } 的变体。我建议您为该库提交错误报告。

作为变通方法,要么按照您对 .asInstanceOf[Link] 所做的操作,要么,如果您想要 js.use(x).as[T] 安全,请使用此:

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