I wonder what's the best way to deal with such a t...
# javascript
e
I wonder what's the best way to deal with such a thing when translating from TS:
Copy code
interface One {
  prop: BaseType
}

interface Two extends One {
  prop: RefinedType // extends BaseType
}
a
https://pl.kotl.in/j2ni1UyDp
Copy code
external open class BaseType
external class RefinedType : BaseType

external interface One {
    val prop: BaseType
}

external interface Two : One {
    override val prop: RefinedType
}
Doest the direct option work?
e
@Artem Kobzar works! But now I understand that it works when prop is
val
, and not when prop is
var
, which is the most common case
So this won't compile
Copy code
external open class BaseType
external class RefinedType : BaseType

external interface One {
    var prop: BaseType
}

external interface Two : One {
    override var prop: RefinedType
}
I'd add this to what a
JsPlainObject
could be able to do 👀 just an hint
We can't bring this functionality because it breaks Kotlin type system correctness
e
Ah makes sense! Maybe we can make it work with a
val
and a custom inline set* method that write to the underlying property? But would methods work with the new plain objects?
a
I mean, it will work in case of creating object, but not for the future mutating of the property
Copy code
@JsPlainObject
external interface One {
    val prop: BaseType
}

@JsPlainObject
external interface Two : One {
    override val prop: RefinedType
}

One(BaseType()) // works
One(RefinedType()) // works
Two(RefinedType()) // works
Two(BaseType()) // Compile-time error

Two(RefinedType()).apply { prop = RefinedType() /* Compile-time error, because you can't mutate the property */ }

Two(RefinedType()).copy(prop = NewRefinedType()) // works
✔️ 1
e
To be clear I'm suggest going from
Copy code
external interface One {
    var prop: BaseType
}
external interface Two : One {
    override var prop: RefinedType
}
to
Copy code
external interface One {
    val prop: BaseType
    open inline fun setProp(p: BaseType): Unit = asDynamic().prop = p
}
external interface Two : One {
    override val prop: RefinedType
    override inline fun setProp(p: RefinedType): Unit = asDynamic().prop = p
}
More or less I guess you can understand where I'm going
I need to check if it compiles tho
Ah nope, it doesn't compile
I recalled I did something similar, but it was on an external class, not an interface
What if you introduce an additional copy function that doesn't create a new object?
Copy code
val modified = Two(RefinedType()).modify(prop = NewRefinedType())
At this point I'm just throwing ideas around lol
t
In case of JSO
var
has no big sense. In wrappers we plan to use
val
for JSO-interfaces even if in TS it's declared as mutable property. P.S. Props - open question
Nearest Kotlin analog - data class. I usually don't use
var
in data classes and use readonly JSO in TS. Both have fine copy methods/syntax. cc @Sergei Grishchenko
e
Yeah I agree that
val
is usually better. But, I'd like to have a way to mutate the object without performing a copy of it every time. See example I made above
t
No problem, use
var
for your properties. Additional bonus - inheritance problems :)
e
I think it depends on the use case, there are sensible places where performing a copy isn't the best choice, hot paths where you want the performance boost, like with avoiding null checks and deep call stacks
t
Yes, looks like case for
var