Hey friends, I've been writing some Kotlin/JS code...
# javascript
a
Hey friends, I've been writing some Kotlin/JS code and had some questions about how to handle JS blobs in a nicer way. I noticed that if I have a method that takes in
data class Foo(val bar: Int)
as a parameter, I can call it from JS and pass in the blob
{"bar": 1}
and it will Just Work. Is this officially supported, or is it just an unreliable side-effect of how Kotlin/JS internally represents data classes? Does this work with nested classes (e.g.,
data class Foo2(val myBar: Bar)
and
data class Bar(...)
)? If I had a class that was declared as
data class Foo3(val bar: SomeEnumClass)
, is there a simple way to allow me to call it from JS using a blob with an
Int
map it to
SomeEnumClass
in Kotlin? Maybe something like an alternate constructor or property with a backing fields?
r
Hi, Kotlin/JS tries to keep original name of publicly accessible property for JS-interop reasons. So while you don’t use kotlin-specific features like instance check or invoke special method (e.g. hashcode) such object works well. For nested classes it also should work until you use kotlin-specific features as well. In case of enum class there is a built-in method of enum
values()
which returns an array of enum entries so it works like this
Copy code
enum class E { Foo, Bar }
E.values()[0] // Foo
E.values()[1] // Bar
a
As an example, if I declare the following in my common code,
Copy code
kotlin
data class Input(val inputType: InputType)

enum class InputType { Foo, Bar }

fun processInput(input: Input) = TODO("somehow process the input")
This does not work in Javascript:
Copy code
javascript
const input = { "inputType": 1 }
processInput(input)
If I define these additional intermediate classes/methods in my Kotlin/JS platform code:
Copy code
kotlin
data class InputJs(val inputType: Int) {
    fun toCommmon() = Input(InputType.values()[inputType])
}

fun processInputJs(input: InputJs) = procesInput(input.toCommon())
Then I can call
Copy code
javascript
const input = { "inputType": 1 }
processInputJs(input)
Is there a way to do this without having to define extra classes/methods?
Is this something that could also be solved if/when JS supports inline enums?
r
JFYI: There is an issue about inline enum classes https://youtrack.jetbrains.com/issue/KT-23823 Now we are considering add inline enums to Kotlin but this feature hasn’t been designed yet. Applying to your case despite whether inline enums are supported or not some additional logic is required (e.g. in kotlinx-serialization) to transform index into corresponding enum entry.
a
is inline enum the only way to handle this case though? It also looks like inline classes in general aren't even supported in JS yet and don't have a target version either: https://youtrack.jetbrains.com/issue/KT-30224
r
We don’t have a plan to fully support inline classes in current K/JS compiler now. We are working hard on new K/JS compiler where this feature is implemented.
👍 1