Kotlin/JS 外部声明 - "Name contains illegal chars that can't appear in JavaScript identifier"

Kotlin/JS external declaration - "Name contains illegal chars that can't appear in JavaScript identifier"

编辑:尚不支持,tracked on Kotlin YouTrack


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

export interface Headers {
  'content-length'?: string;
}

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

external interface Headers {
    var `content-length`: String? get() = definedExternally; set(value) = definedExternally
}

但是现在编译器抱怨:

Name contains illegal chars that can't appear in JavaScript identifier

它确实不能出现在 JS 标识符中,但它不必出现。 所有 Kotlin 访问此 属性 就像:

val length = headers.`content-length`

如果编译为 const length = headers["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"
            }
        }
}

试试这个,从字面上看:

export interface Headers {
  this['content-length']?: string;
}

我无法让它在外部工作,但这是一个很好的连字符 hack,可能会有帮助。以下是您将如何使用它:与其定义外部对象,不如在它所在的位置使用 jsObject{}。您可以嵌套它们,但一定要在每一层中明确包含动态标识符,尤其是当您必须在不同层中使用多个 this(es) 来克服连字符问题时。这是您的解决方案:

val Header = jsObject<dynamic> {
    this["content-length"] = "something"
}

让“这个”成为你的一个教训。

我建议通过在 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 对象(参见 playground):

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
}