是否可以忽略仅限 JVM 的属性并安全地导出到 JavaScript?

Is it possible to ignore JVM-only properties and safely export to JavaScript?

我在这个 Play with ScalaJS example 之后有一个基本的项目设置。我发现使用相同模式的其他示例会将案例 classes(模型)与其传统上的伴随对象分开。也就是说,案例 class 将存在于 "shared" 子项目中,而 "companion object" (实际上只是一些对象)将存在于 "server" 子项目中。

最好将这两个放在同一个文件中(即将重要的东西放在真正的伴随对象中),因为将类型-class 实例放在那里并让它们解析非常方便适当地。例如:

case class User(id: Int, name: String)

object User {

  val default = User(1, "Guest")

  // I need this for the back-end, but don't need to export to JS
  implicit val reads: Reads[User] = ...
}

不幸的是,这会导致链接错误,因为 Reads 类型仅存在于 JVM 上(只是其中之一)。但是,如果我要将 val reads 移动到另一个文件中,Reads[User] 的隐式解析将破坏整个 "server" 子项目,而不添加显式导入(这会很烦人)。

是否可以显式忽略 ScalaJS 导出中的某些属性,同时仍然允许它们为 JVM 编译?我希望导出 User 案例 class,甚至可能导出其伴随对象的其他属性,但仅可在不中断前端的情况下忽略 JVM 上存在的其他属性。

我过去解决这个问题的方法(在 Scala.js 代码库本身)是通过 PlattformExtensions 混合到交叉编译对象中的特征,但对于 JVM 和 JS 是不同的:

object User extends UserPlattformExtensions {
  val default = User(1, "Guest")
}

在您的 JVM 项目中:

trait UserPlattformExtensions {
  implicit val reads: Reads[User] = ???
}

在你的 JS 项目中:

trait UserPlattformExtensions

在您的文件组织中(使用标准交叉项目),这将如下所示:

project/
  shared/
    src/main/
      User.scala
  jvm/
    src/main/
      UserPlattformExtensions.scala
  js/
    src/main/
      UserPlattformExtensions.scala

不存在依赖性问题,因为对于编译器来说,源文件的汇编如下:

sources in projectJVM:
  shared/src/main/User.scala
  jvm/src/main/UserPlattformExtensions.scala

sources in projectJS:
  shared/src/main/User.scala
  jvm/src/main/UserPlattformExtensions.scala

因此对于每个单独的编译 运行,整个构造只是一个继承自特征的对象。源代码来自哪个源目录与编译无关。