How to access native JS object as a Map<String, Any>?

In JS, if there is an array in the native layer, I can use it in kotlin as an Array<T>.  How can I do a similar thing with maps/objects? If I try something like this:

  val m: Map<String, Any> = …
  for (k in m.keySet()) {  …  }
  m[“foo”]

where m is a object in native JS, keySet etc is undefined.

Rob

Right way to do it now is cast object to Json, but it's not map.

If you really want to get Map you can wrap your object by Map implementation from stdlib, like:

import java.util.HashMap

fun <V> PrimitiveHashMap(container: dynamic): HashMap<String, Any> {
    val m = HashMap<String, Any>().asDynamic()
    m.map = container
    val keys = js("Object.keys")
    m.`$size` = keys(container).length
    return m
}

fun main(args: Array<String>) {
    val e = PrimitiveHashMap<Int>(js("({})"))
    println(e)
    
    val m = PrimitiveHashMap<Int>(js("({aaa: 1, bbb: 2})"))
    println(m)
}

But note, please, it is hack which depends to implementation details and they can be changed in the future.

I created issues(KT-5653, KT-5654) which covered this, feel free to vote or star them for get updates.

2 Likes

Great, thanks!

Looks like this hack no longer works. Is there an updated version?

Rob

I updated answer

Shouldn’t this be inside the JS stdlib?

2 Likes

Another way is just to iterate over the key-value pairs of a JS object:

fun entriesOf(jsObject: dynamic): List<Pair<String, Any?>> =
    (js("Object.entries") as (dynamic) -> Array<Array<Any?>>)
        .invoke(jsObject)
        .map { entry -> entry[0] as String to entry[1] }

fun mapOf(jsObject: dynamic): Map<String, Any?> =
    entriesOf(jsObject).toMap()
3 Likes