is there a clean way to represent a common API cla...
# javascript
t
is there a clean way to represent a common API class that returns a js Promise in KotlinJS, and a Deferred (or equivalent) in Kotlin JVM? I tried using an expect/actual pairing as follows: common:
Copy code
expect class Later<T>
JS:
Copy code
actual typealias Later<T> = Promise<T>
JVM:
Copy code
actual typealias Later<T> = Deferred<T>
But that doesn't seem to work because of the out variance on the Promise/Deferred, i.e. Promise<out T>. This feels like a common use-case, so wondering what the usual solution is? Would prefer not to wrap each method on each platform for maintenance reasons...
✔️ 1
also note the API will be consumed by regular javascript, so need a platform-native return type
b
Usually this is solved by typealias on one platform and wrapper on another. However why don't you return deferred on both? On js it has toPromise() helper fun to expose it to other js consumers.
t
yeah I can do a wrapper, it's just ugly on both platforms - feels like the sort of thing that should be possible
b
It's only ygly for one platform, the other is just a typealias
t
for the wrapper, are you suggesting something along the lines of MyDeferred(d : Deferred) : Deferred by d ?
a
I think what you are seeing here is that the two platforms are actually not the same. Because of this, they need to be modelled differently. i.e. on JS your code has to return Promises and on JVM it has to return Deferred. There is no Kotlin common framework that successfully abstracts away this difference, so you need to implement the abstraction yourself.
In my own code, I have a Kotlin/JVM class that has a bunch of suspend functions and then Kotlin JS code that wraps it, deals with the coroutine setup and returns Promises..
b
@Tristan Blakers that's the ideal solution if you're able to wrap an interface. For regular classes you'll need to rewire all your methods manually.
t
yep, I was hoping to bridge the gap using expect/actual typealiases rather than a wrapper class. The only thing that stops that working is the out variance on the type Promise/Deferred type parameters - was mainly hoping for a workaround that enables a typealias
b
Why not typealias promise then and wrap deferred?
s
@Tristan Blakers Is it this issue? https://youtrack.jetbrains.com/issue/KT-21846
t
yep, that's the issue - can't find a way to use an
Copy code
actual typealias
on either promise or deferred because of the <out T>
It does work when the type variable is just <T> tho, odd
👍 1