In Kotlin/JS, how can I initialize a JavaScript In...
# javascript
m
In Kotlin/JS, how can I initialize a JavaScript Integer? I'm creating typings for a library (Discord Embedded App SDK) and to set an activity they have a
Timestamps
object that expects two integers: A
start
and
end
timestamps. These timestamps are Epoch millis. The library expects integers for these timestamps: https://discord.com/developers/docs/events/gateway-events#activity-object-activity-timestamps But that's where the issue lies: I can't figure out a way to initialize a JavaScript Integer! • A Kotlin Int doesn't work because converting a epoch millis to a Kotlin Int causes it to overflow and go into the negatives • A Kotlin Long doesn't work due to the way Kotlin Long works in Kotlin/JS • A Kotlin BigInt doesn't work because the backend (in this case, Discord's RPC protocol) complains that it isn't a number • A Kotlin String doesn't work because the backend complains that it isn't a number The only way I found to make it work is by initializing the number via
js
, but I wonder if there's a better way to do this?
Copy code
discordSDK.commands.setActivity(
                        SetActivityRequest(
                            activity = Activity(
                                0, // Changes the top of the activity title in the profile
                                "PixelBloom",
                                "Placing pixels at ${cursor.value?.x}, ${cursor.value?.y}",
                                timestamps = Timestamps(
                                    start = js("new Date().getTime()")
                                )
                            ).also {
                                console.log("Generated Activity: ", it)
                            }
                        )
                    )
b
Will Double do? Sure, it’s not an integer, but it’s the closest type to JS
number
that Kotlin has.
2
e
JS "integer" is just a double that happens to be integral
3
JS APIs that that want larger numbers but don't accept strings are pretty bad though, JS is unable to represent many exact integers above 2^53 (because that's the limit of using double-precision floating point numbers to represent integers)
e
Define the external using `Double`s.
Copy code
external class Timestamps(
  start: Double? = definedExternally,
  end: Double? = definedExternally,
)
Which will then accept a
Date.now()
without conversion. Or, if you prefer using Kotlin's built-in clock
Copy code
val start = Clock.System.now().toEpochMilliseconds()
timestamps = Timestamps(start = start.toDouble())
t
EpochTimeStamp
is here 😉
Potentially it can be opaque interface 😉
m
Thanks everyone! I don't know why I didn't try using
Double
before but sure enough it worked 🙂
Copy code
@JsPlainObject
external interface Timestamps {
    var start: Double?
    var end: Double?
}
About the EpochTimeStamp, that would require something like this, right? @turansky
Copy code
fun Long.toEpochTimeStamp() = this.toDouble().unsafeCast<EpochTimeStamp>()
and then
Copy code
@JsPlainObject
external interface Timestamps {
    var start: EpochTimeStamp?
    var end: EpochTimeStamp?
}
(this does work because EpochTimeStamp is a typealias of Int53 and Int53 is a typealias of Double, but I don't know if it is correct)
t
You can use
EpochTimeStamp
right now instead of
Double
. No additional
unsafeCast
required.
👀 1
In similar case we add interfaces (like this). For numbers it's not so easy :(