Kotlin/JS外部声明-“;Name包含可以';t出现在JavaScript标识符中“;

Kotlin/JS外部声明-“;Name包含可以';t出现在JavaScript标识符中“;,kotlin,kotlin-js,kotlin-js-interop,Kotlin,Kotlin Js,Kotlin Js Interop,编辑:尚不支持此操作,并且 我正在尝试编写一个与以下Typescript接口匹配的Kotlinexternal声明(这是通过标题['content-length']表示JavaScript访问的有效TS): Dukat生成以下内容,这些内容应被视为有效: external interface Headers { var `content-length`: String? get() = definedExternally; set(value) = definedExternally

编辑:尚不支持此操作,并且


我正在尝试编写一个与以下Typescript接口匹配的Kotlin
external
声明(这是通过
标题['content-length']
表示JavaScript访问的有效TS):

Dukat生成以下内容,这些内容应被视为有效:

external interface Headers {
    var `content-length`: String? get() = definedExternally; set(value) = definedExternally
}
但现在编译器抱怨:

Name包含不能出现在JavaScript标识符中的非法字符

确实,它不能出现在JS标识符中,但它不一定要出现。所有Kotlin访问此属性的方式如下:

val length=标题。`content length`
如果编译为
const length=headers[“content length”]
,则可能有效

我尝试使用
@JsName
以以下方式解决此问题:

  • @JsName(“内容长度”)
  • @JsName('content-length')
  • @JsName(“内容长度”)
但所有这些都失败了,因为它们只允许有效JS标识符的字符串。
有办法解决这个问题吗?

问题是连字符
-
Javascript中不是有效的标识符。这意味着您不能像这样声明变量:

var content-length = 4
您只能这样做:
var contentLength=4

Kotlin Kultiplatform不允许您编写无法编译到目标平台的通用代码,这就是为什么即使这是有效的Kotlin代码:

var `content-length`: String? // ...
由于Javascript约束,您仍然无法在多平台环境中使用它


还请注意,虽然这可能是有效的Typescript代码,但Kotlin没有Typescript目标,只有Javascript目标,所以请记住这一点。

JSON中允许连字符,我相信如果您使用记号(```),Javascript中可能允许连字符。我在使用jsObject时遇到了同样的连字符问题,这就是解决方案

我的连字符问题和此解决方案:

pluginsOpts = jsObject<dynamic> {
        this["grapesjs-tabs"] = jsObject<dynamic> {
            tabsBlock = jsObject<dynamic> {
                category = "Extra"
            }
        }
}
我不能让它在外部工作,但这是一个很好的连字符黑客可能会有所帮助。下面是您将如何使用它:您将使用jsObject{}代替它,而不是定义外部对象。您可以嵌套它们,但一定要在每一层中显式地包含动态标识符,特别是当您必须在不同层中使用多个this来克服连字符问题时。这是您的解决方案

val Header = jsObject<dynamic> {
    this["content-length"] = "something"
}
val Header=jsObject{
此[“内容长度”]=“某物”
}

让“this”成为您的一课。

我建议通过定义一个空接口来代替Kotlin中的此类对象,再加上一个扩展属性来获取和设置值来解决此问题:

external interface KHeader // stands in for JavaScript objects with content-length property

var KHeader.contentLength: String
   get() = this.asDynamic()["content-length"]
   set(value) { this.asDynamic()["content-length"] = value }
通过这种方式,您可以将Kotlin中的
Header
JavaScript对象与camel case一起使用(请参阅):


我理解您关于标识符的观点,也理解编译错误的含义,但并非每个声明都必须编译为JS标识符。我当然明白,在Kotlin中编写
val`content length`=2
会触发编译器错误,但
val length=headers.`content length`
应该有效,并编译为
let length=headers[“content type”]
。这里我们讨论的是一个类型声明,它根本不必出现在生成的JS中。事实上,JS中关于接口的重要内容只是属性访问,正如我所展示的,这是有效的。我不熟悉Javascript编译器,因此我恐怕无法进一步推测(不幸的是,我也不熟悉Kotlin/JS编译器的细节。但在这种情况下,JS库已经存在,所以我知道这可以在JS中使用,我只希望能够在Kotlin中正确地键入它,而不必诉诸
动态
。我相信这是KJS中的一个真正的错误。'GrapeJS lory slider':{}是有效的JS,但是没有任何方法可以让kotlin传输到它。相当大的问题…这意味着没有人可以与使用该约定的javascript包交互…如果我没有弄错的话。在KJS中,我应该能够执行
grapesjs lory slider
=jsObject{}但是你的
标题类型是如何在这里声明的呢?这就是问题的全部要点……我已经改变了答案,用一个相关的想法来实际回答你的问题!这里没有在Kotlin中定义标题类型的地方。问题的重点是找到一种方法来静态正确地键入这个标题rface/class,而不是找到构造实例的方法。
val Header = jsObject<dynamic> {
    this["content-length"] = "something"
}
external interface KHeader // stands in for JavaScript objects with content-length property

var KHeader.contentLength: String
   get() = this.asDynamic()["content-length"]
   set(value) { this.asDynamic()["content-length"] = value }
fun main() {
    val jsObject = js("{}")
    jsObject["content-length"] = "44"
    val randomHeader = jsObject as KHeader
    println(randomHeader.contentLength) // prints 44
    randomHeader.contentLength = "55"
    println(randomHeader.contentLength)  // prints 55
}