在Scala.js中,如何最好地从JS外立面创建符合特征的对象?

Jea*_*let 2 casting object-literal type-safety scala.js

假设我在Scala.js中具有此定义,用于我正在使用的某些库的函数的返回类型:

@native
trait Link extends Object {
  val href: String = native
  val title: String = native
}
Run Code Online (Sandbox Code Playgroud)

在Scala代码中,定义符合此要求的对象文字的最佳,类型安全的方法是什么?我认为这个use(...).as[...]技巧会起作用:

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

但这会产生错误:

AnyRef {val href:字符串;val title:String}不会导出getter href:String

为什么?

我也尝试过此方法,并且按预期失败了:

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

具有scala.scalajs.js.Dynamic的scala.scalajs.js.Object没有getter href:字符串

最后,我还尝试了以下方法:

val link = new Link {
  override val href = "value1"
  override val title = "value2"
}
Run Code Online (Sandbox Code Playgroud)

并得到

Scala.js定义的JS类无法直接扩展本机JS特性

现在,我正在这样做:

val link = js.Dynamic.literal(
  href = "value1",
  title = "value2"
).asInstanceOf[Link]
Run Code Online (Sandbox Code Playgroud)

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

sjr*_*jrd 5

库应声明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]
Run Code Online (Sandbox Code Playgroud)