Background: Options-objects in JavaScript
A common concept in JavaScript is something like this:
function MyLibrary(options) {
if (options.optionA) { /* ... */ }
if (options.optionB) { /* ... */ }
if (options.flagC) { /* ... */ }
}
new MyLibrary({optionA: "foo", flagC: true})
So basically we have an "options"-object that contains many properties which are all optional.
The question: How to interact with that from Kotlin?
In Kotlin we would probably rather use named parameters with default values. However I would like to interact with an existing JavaScript-Library, which uses the concept described above. How can I describe and use that library from Kotlin? Of course it should be as type safe as possible.
What I have tried so far
Here is what I came up with:
interface Options {
var optionA: String
var optionB: Int
var flagC: Boolean
}
external class MyLibrary(options: Options)
fun myFunWithApply() {
MyLibrary(Any().unsafeCast<Options>().apply {
optionA = "foo"
flagC = true
})
}
That does work, it also gives code completion for the options which is great, while it is not as short as the original JavaScript it feel OK considering its length. However... Are there better ways? Is there a way to get along without unsafeCast
?
Yes, sure.
Usage:
The
IOptions
external interface is needed to preventOptions
member names from being mangled. TheOptions
class cannot be external on itself because there is no such class/constructor defined in JS.The caveat is that the generated JS code is going to be slightly less efficient — there will be a whole additional class (
Options
) and a constructor invocation with parameters being assigned to properties, instead of just a JS object literal. However, once the code being involved gets jitted, it will probably make no difference.