gpt4 book ai didi

scala - Scala.js 中 JS 库的类型化外观

转载 作者:行者123 更新时间:2023-12-01 12:37:19 31 4
gpt4 key购买 nike

我正在尝试为我的图书馆编写一个类型化的外观 Paths.js , 关注 the official guide .

我希望能够翻译如下调用:

var Polygon = require('paths-js/Polygon');
var polygon = Polygon({
points: [[1, 3], [2, 5], [3, 4], [2, 0]],
closed: true
});

进入

val polygon = Polygon(points = List((1, 3), (2, 5), (5, 6)), closed = true)

但我不确定我需要做什么才能达到这一点。

我所做的是类似下面的事情

type Point = (Number, Number)
trait PolygonOpt {
val points: Array[Point]
val closed: Boolean
}
@JSName("paths.Polygon")
object Polygon extends js.Object {
def apply(options: PolygonOpt): Shape = js.native
}

然后,我可以调用它

class Opt extends PolygonOpt {
val points: Array[Point] = Array((1, 2), (3, 4), (5, 6))
val closed = true
}
val opts = new Opt
val poly = Polygon(opts)

我对此有一些疑问:

  • 我正处于编译所有内容的时刻,但生成的 javascript 在调用时失败。我相信这是因为我正在传递 PolygonOpt 的实例,而运行时需要一个 javascript 对象文字
  • Point的定义翻译成一个包含两个组件的 js 数组?
  • 我希望能够重载 Polygon.apply喜欢def apply(points: Seq[Point], closed: Boolean): Shape , 但 scala.js 不允许我在 Polygon 中编写方法实现因为它扩展了 js.Object

此外,我有一个使用 common.js 的库版本(它被分成几个文件,每个组件一个)和另一个可以用作单个的 <script>标签,将所有内容放在命名空间 paths 下(这是我现在正在使用的那个)。

哪个更适合 Scala.js 包装器?

最佳答案

首先,请务必阅读 JS interop doc ,包括 calling JavaScript guide .我想你已经这样做了,因为你已经有了一些合理的东西。但是你应该特别注意那些说 Scala 类型和 JavaScript 类型完全无关的部分,除非明确提到。

因此,Int 是一个合适的 JS number(在 int 范围内)。但是 Array[Point] 与 JavaScript 数组无关。 Tuple2(例如 (1, 3))更是如此。所以:

Is the definition of Point translated into a js array with two components?

不,不是。因此,JavaScript 完全无法理解它。是opaque .

更糟糕的是,PolygonOpt,因为它不扩展 js.Object,所以对于 JavaScript 也是完全不透明的,这解释了为什么您看不到字段 关闭

首先要做的是使用 JavaScript 可理解的类型(扩展 js.Object)准确输入您的 JS API。在这种情况下,它看起来像这样:

type JSPoint = js.Array[Int] // or Double

trait PolygonOpts extends js.Object {
val points: js.Array[JSPoint] = js.native
val closed: Boolean = js.native
}

@JSName("paths.Polygon")
object Polygon extends js.Object {
def apply(options: PolygonOpt): Shape = js.native
}

现在,要创建 PolygonOpts 的实例并不是一件容易的事。为此,请参阅 this SO question :

object PolygonOpts {
def apply(points: js.Array[JSPoint], closed: Boolean): PolygonOpts = {
js.Dynamic.literal(
points = points,
closed = closed
).asInstanceOf[PolygonOpts]
}
}

最后,您可以首先使用隐式扩展公开您想要的 Scala 式 API:

import js.JSConverters._

object PolygonImplicits {
implicit class PolygonObjOps(val self: Polygon.type) extends AnyVal {
def apply(points: List[(Int, Int)], closed: Boolean): Shape = {
val jsPoints =
for ((x, y) <- points.toJSArray)
yield js.Array(x, y)
Polygon(PolygonOpts(jsPoints, closed))
}
}
}

隐式扩展是编写 Scala 方法的方法,这些方法似乎可用于扩展 js.Object 的对象,因为正如您发现的那样,您实际上无法在内部实现方法一个 js.Object

关于scala - Scala.js 中 JS 库的类型化外观,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28558820/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com