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

时间:2017-07-19 11:46:01

标签: casting scala.js type-safety object-literal

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

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

在Scala代码中,定义符合此标准的对象文字的最佳,类型安全方法是什么?我认为use(...).as[...]技巧可行:

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

但这会产生错误:

  

AnyRef {val href:String; val title:String}不导出getter href:String

为什么?

我也试过这个,并且正如预期的那样失败了:

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

给出

  

scala.scalajs.js.Object与scala.scalajs.js.Dynamic没有getter href:String

最后,我也尝试了这个:

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

得到了

  

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

现在,我正在这样做:

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

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

1 个答案:

答案 0 :(得分:4)

图书馆应将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]