I'd like to write some generic conversion logic fr...
# javascript
b
I'd like to write some generic conversion logic from @JsPlainObject types to internal Kotlin data classes; the main issue here is that the external interface needs to extend from an interface that contains non exported types
Copy code
@JsExport
@JsPlainObject
external interface Hello: Event<DataHello> {
    val greeting: String
}

sealed interface Event<T> {
    fun toKt(): T
}

data class DataHello(
    val greeting: String
)

@JsExport
fun <T> publish(event: Event<T>) {
    val data = event.toKt()
}
right now, I need to do something like this:
Copy code
suspend fun <T : Any> publish(event: OEEvent): OEClientResponse {
        when (event) {
            is HelloWorldEvent,
            is OtherEventEvent -> {
                val result = client.publish(event.toKt())
                return result.toJs()
            }

            else -> throw IllegalArgumentException("Not a supported event")
        }
    }
is there a better way? I'd like to do something like the attached screenshot where one interface is exported to JS but the other one is kept internal I'd need a way to create an interface that is only implemented in Kotlin for that type and is not exported to TypeScript
t
Looks like missed integration with serialization plugin.
Idea - use data classes only, which will be serailized/deserialized when you do call from JS
b
you mean like serialize @JsPlainObject to JSON, then deserialize onto data classes, then those data classes serialize to JSON again before the call?
or is there a way to skip JSON serialization/deserialization for the JsPlainObject parts?
furthermore, there's a question on how to convert JS Maps to Kotlin Maps
t
You can serialize data classes to JS objects
b
do you have an example?
another downside would probably be keeping the plain objects and data classes in sync
t
KSP can do this
Goal - use data classes everywhere
JSO - for JS API only
b
yeah, that'd be cool, but I'd be writing an extensive compiler plugin I suppose?
t
It depends on your code base
You can start from simple Gradle plugin, which will generate JSO interfaces
b
probably worthwhile once the code base grows, I'll keep that in mind
strictly speaking should probably be done by the JS compiler itself (or the plain objects plugin)
I'd imagine it's quite a common use case
t
Yes
It's possibility to avoid JS specific logic/classes in common code
In Kotlin you use
List
- JS see
Array
and so on
You write:
Copy code
data class ABC(
    aaa: List<A>,
    bbb: Map<String, B>,
    ccc: MyEnum,
)
JS see:
Copy code
interface ABC {
    readonly aaa: ReadonlyArray<A>
    readonly bbb: Map<string, B>
    readonly ccc: "c1" | "c2" | "c3"
}
b
yeah, there's a bunch of additional niceties that could be done here
t
It's what I expect from JS interop by default. I write Kotlin (without JS specific types) - Kotlin/JS give me cool integration with JS world
b
is there an open issue that you know of?
t
No
b
otherwise I'd probably file a feature request
kodee happy 1
t
I will add it to this one 😉
🙌 1
I mean - you will create separate issue and I will mention it in meta issue
b
Thank you for clarifying