2

编辑: Kotlin YouTrack尚不支持和跟踪


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

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以下方式解决它:

  • @JsName("content-length")
  • @JsName("'content-length'")
  • @JsName("\"content-length\"")

但是所有这些都失败了,因为它们只允许作为有效 JS 标识符的字符串。有没有办法解决这个问题?

4

3 回答 3

3

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

var content-length = 4

你只能这样做:var contentLength = 4

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

var `content-length`: String? // ...

由于Javascript的限制,您仍然不能在多平台环境中使用它。

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

于 2019-06-04T08:58:54.907 回答
2

我建议通过定义一个空接口来代替 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 }

通过这种方式,您可以Header在 Kotlin 中使用带有驼峰式大小写的 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
}
于 2021-01-31T11:50:52.417 回答
1

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

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

pluginsOpts = jsObject<dynamic> {
        this["grapesjs-tabs"] = jsObject<dynamic> {
            tabsBlock = jsObject<dynamic> {
                category = "Extra"
            }
        }
}

试试这个,从字面上看:

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

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

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

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

于 2020-08-22T20:28:27.090 回答