1
votes

Déclaration externe Kotlin / JS - "Le nom contient des caractères illégaux qui ne peuvent pas apparaître dans l'identifiant JavaScript"

EDIT: Ceci n'est pas encore pris en charge et suivi sur Kotlin YouTrack


J'essaie d'écrire une déclaration externe correspondant à l'interface dactylographiée suivante (c'est TS valide pour représenter les accès JavaScript via headers ['content-length'] ):

val length = headers.`content-length`

Dukat génère ce qui suit, qui doit être considéré comme valide:

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

Mais maintenant, le compilateur se plaint:

Le nom contient des caractères illégaux qui ne peuvent pas apparaître dans l'identifiant JavaScript

Il est vrai qu'il ne peut pas apparaître dans un identifiant JS, mais ce n'est pas obligatoire. Tous les accès Kotlin à cette propriété comme:

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

pourraient être valides si compilés en const length = headers ["content-length"] code >.

J'ai essayé d'utiliser @JsName pour contourner le problème de la manière suivante:

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

Mais tous échouent car ils n'autorisent que les chaînes qui sont des identifiants JS valides. Y a-t-il un moyen de contourner ce problème?


0 commentaires

3 Réponses :


2
votes

Le problème est que les tirets - ne sont pas des identifiants valides dans Javascript . Cela signifie que vous ne pouvez pas déclarer une variable comme celle-ci:

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

Vous ne pouvez faire que: var contentLength = 4

Kotlin Kultiplatform ne vous permettra pas d'écrire du code commun qui ne peut pas être compilé sur une plate-forme cible, c'est pourquoi même s'il s'agit d'un code Kotlin valide:

var content-length = 4

vous ne pouvez toujours pas utilisez-le dans un environnement multiplateforme en raison des contraintes Javascript .

Veuillez également noter que même s'il s'agit d'un code Typescript valide, Kotlin n'a pas une cible Typescript, uniquement Javascript, alors gardez cela à l'esprit.


4 commentaires

Je comprends votre point sur les identifiants, et je comprends ce que signifie l'erreur de compilation, mais toutes les déclarations ne doivent pas être compilées avec un identifiant JS. Je comprendrais certainement qu'écrire val `content-length` = 2 dans Kotlin déclencherait une erreur de compilation, mais val length = headers.`content-length` devrait être valide et compilé en let length = headers ["content-type"] . Ici, nous parlons d'une déclaration de type, qui n'a pas du tout à apparaître dans le JS produit. En fait, ce qui compte dans JS en ce qui concerne une interface, c'est uniquement l'accès à la propriété, et c'est valable comme je l'ai montré.


Je ne suis pas familier avec le compilateur Javascript, donc je ne peux plus spéculer, j'en ai peur. :(


Je ne connais malheureusement pas non plus les détails du compilateur Kotlin / JS. Mais dans ce cas, la bibliothèque JS existe déjà, donc je sais que c'est possible d'utiliser dans JS, j'aimerais juste pouvoir taper ceci correctement dans Kotlin sans recourir à dynamic .


C'est un vrai bug dans KJS je crois. 'grapesjs-lory-slider': {} est un JS valide, mais il n'y a aucun moyen de faire transpiler Kotlin vers cela. Assez gros problème ... cela signifie que personne ne peut s'interfacer avec un package javascript qui utilise cette convention ... si je ne me trompe pas. dans KJS, je devrais pouvoir faire grapesjs-lory-slider = jsObject {}



1
votes

Les traits d'union sont autorisés dans les JSON, et je pense qu'ils peuvent être autorisés dans JavaScript si vous utilisez des graduations (``). J'ai eu ce même problème de trait d'union lors de l'utilisation de jsObject, c'était la solution, littéralement.

Mon problème de trait d'union et cette solution:

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

Essayez ceci, littéralement: p >

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

Je ne pouvais pas faire fonctionner cela dans un externe, mais c'était un bon hack de trait d'union qui pourrait aider. Voici comment vous l'utiliseriez: Plutôt que de définir un objet externe, vous utiliseriez un jsObject {} à sa place. Vous pouvez les imbriquer, mais assurez-vous d'inclure explicitement l'identifiant dynamique dans chaque couche, surtout si vous devez utiliser plusieurs éléments dans différentes couches pour surmonter le problème du trait d'union. Ceci est votre solution

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

Que "ceci" soit une leçon pour vous.


0 commentaires

0
votes

J'ai résolu ce problème dans mon application en écrivant une fonction de bibliothèque. Il profite du type dynamique (retourné par la fonction js ) pour attribuer des valeurs à un objet sans la vérification du compilateur.

val headers = jsObjectOfPairs( "content-length" to 552 ) as Headers

Ensuite, vous avez une fonction que vous peut construire un objet JavaScript arbitraire sans restrictions sur les caractères dans les clés de propriété, par exemple:

fun jsObjectOfPairs( vararg pairs: Pair<String,Any> ): dynamic {
   val jsObject = js( "{}" )
   pairs.forEach {
      jsObject[ it.key ] = it.value
   }
   return jsObject
}


0 commentaires