【问题标题】:Typesafe wrapper around javascript object in scala.jsscala.js 中 javascript 对象的类型安全包装器
【发布时间】:2015-08-12 20:49:13
【问题描述】:

我想围绕一个 javascript 库编写一个 scala.js 包装器,该库有一个可以像这样实例化的对象:

new Point({x: 10, y: 12})

似乎很简单。 我想要一个坐标案例类和一个围绕该点的包装器。

case class Coord(x: Int, y: Int)
class Point(coord: Coord) extends js.Object

这显然是行不通的,因为 case 类没有被翻译成对象字面量。我当然可以摆脱 Coord 案例类,而是将 js.Dynamic.literal 传递给构造函数,但这不是很安全。

我还有什么其他选择?我是否必须编写一个更高级别的包装器来接受 Coord 并将其转换为对象文字,然后再将其传递给 Point 对象?

【问题讨论】:

标签: scala.js


【解决方案1】:

你有几个选择:

选项对象

trait Coords extends js.Object {
  def x: Int = js.native
  def y: Int = js.native
}

class Point(coords: Coords) extends js.Object

和Coords 的类型安全工厂。详情在this SO post

点工厂/更高级别的包装器

case class Coords(x: Int, y: Int)

object Point {
  def apply(coords: Coords): Point = new Point(
    js.Dynamic.literal(x = coords.x, y = coords.y))
}

将案例类解释为选项对象

trait PointCoords extends js.Object {
  def x: Int = js.native
  def y: Int = js.native
}

@JSExportAll
case class Coords(x: Int, y: Int)

val c = Coords(1, 2)
new Point(js.use(c).as[PointCoords])

【讨论】:

  • 伴生对象真的很棒。这个问题确实是重复的,但很难找到其他问题。作为替代解决方案建议(不确定这是否可行):不能将参数标记为“文字”以便 scala.js 可以自动转换案例类吗?类 Point(@JSLiteral coors: Coors) 扩展 js.Object
  • @JSExport 之间有什么区别? (参数上的@JSExport 将起作用并按照您的预期执行)。
  • 那我对 JSExport 的理解就不同了。对我来说,看起来 JSExport 正在导出(案例)类的字段以在 JS 中可用。我反过来想。注释 JS 外观构造函数或方法参数以将对象转换为文字,无论对象类型是否被注释。但是阅读 JSExport 文档,我想它也应该这样工作。在我的特定示例中,它现在无法正常工作。我仍然需要调试问题所在。
  • 好的,调试好了。 JS 库使用 hasOwnProperty 来检查传递的对象上是否存在属性。这对于我通过案例类上的 JSExport 公开的属性返回 false。然后库会引发错误。
  • 确实如此。由于具有JSExported 属性的对象没有它作为 own 属性。它是通过原型链继承的。如果你需要一个拥有自己属性的对象,你必须使用js.Dynamic.literal。
猜你喜欢
  • 1970-01-01
  • 2017-07-31
  • 2019-10-17
  • 1970-01-01
  • 2019-07-17
  • 1970-01-01
  • 2018-06-30
  • 1970-01-01
  • 2011-10-26
相关资源
最近更新 更多