如何在 KotlinJs 中生成主体中带有 `this.field=value` 的 javascript 函数

How to generate a javascript function with `this.field=value` in body, in KotlinJs

当我将 KotlinJS 与 riot 一起使用时,它需要如下函数来定义标签:

function (opts) {
    var self = this
    self.name = "sample"
    self.message = "init-message"

    self.onCreate = fun(opts: dynamic) {
        self.message = opts.message
    }

    self.click = fun() {
        self.message = "Clicked!"
    }
}

虽然我可以这样写 Kotlin 代码:

fun(opts: dynamic) {
    val self = js("this")

    self.name = "sample"
    self.message = "init-message"

    self.onCreate = fun(opts: dynamic) {
        self.message = opts.message
    }

    self.click = fun() {
        self.message = "Clicked!"
    }
}

但是你可以看到它有几个问题:

  1. 我们必须使用一些 js("this") 技巧
  2. self.name,self.message,类似的,函数体中到处都是动态代码

如何避免它们?我想尽可能多地编写纯粹的、类型安全的 Kotlin 代码。

并且,是否可以预先定义一个结构更清晰的class,例如:

class MyTag {
   val name = "sample"
   var message = "init-message"
   fun onCreate() {}
   fun click() {}
}

我可以接受对 class 进行一些转换以生成所需的函数。

可能的解决方案可能会 js("this") 转换为已知的 kotlin 类型。 虽然 js() 仍然存在,但它的用法非常局限,而且代码实际上是 type-safe。

下面的代码生成了你在 js 中需要的东西

interface MyTag {
    var name: String

    var message: String

    var onCreate: (dynamic) -> Unit

    var click: () -> Unit
}

inline fun <T> builder(block: T.() -> Unit) = block(js("this"))

fun tagFunction(opts: dynamic) = builder<MyTag> {
    name = "sample"

    message = "init-message"

    onCreate = { message = opts.message }

    click = { message = "Clicked!" }
}