-
Notifications
You must be signed in to change notification settings - Fork 144
Description
Introduction
Following the previous proposal for buildReadableMap and buildReadableArray DSLs (which align with Kotlin’s builder pattern), I would like to propose adding factory functions for creating WritableMap and WritableArray.
In the Kotlin standard library, mutable collections are typically created using factory functions like mutableMapOf(...) or mutableListOf(...). Introducing writableMapOf(...) and writableArrayOf(...) to React Native’s Android codebase would provide a consistent, idiomatic way to initialize mutable native maps and arrays.
Details
Currently, initializing a WritableMap with values requires imperative calls:
val params = Arguments.createMap().apply {
putString("name", "hyunwoo lee")
putInt("age", 28)
putBoolean("loveRN", true)
}With the proposed factory functions, developers can initialize mutable maps and arrays using the familiar vararg syntax found in Kotlin’s standard library:
val params = writableMapOf(
"name" to "hyunwoo lee",
"age" to 28,
"loveRN" to true
)
val fruits = writableArrayOf("apple", "banana", "cherry")This significantly reduces boilerplate when passing arguments to JS, emitting events, or resolving Promises with simple data structures.
Proposed API
The API mirrors the standard library's mutableMapOf and mutableListOf:
/**
* Creates a WritableMap with the given key-value pairs.
*/
fun writableMapOf(vararg pairs: Pair<String, Any?>): WritableMap
/**
* Creates a WritableArray with the given elements.
*/
fun writableArrayOf(vararg elements: Any?): WritableArrayUsage Examples:
// Sending an event with data
sendEvent("onPress", writableMapOf(
"x" to 100,
"y" to 200,
"metadata" to writableMapOf( // Nested creation
"timestamp" to System.currentTimeMillis()
)
))
// Resolving a promise with a mixed array
promise.resolve(writableArrayOf(1, "success", true))Discussion points
Type Safety vs. Developer Experience (...Of factory methods)
Unlike the buildReadableMap DSL, which uses function overloading to enforce type safety at compile-time, the proposed writableMapOf factory relies on vararg pairs: Pair<String, Any?>.
This introduces a trade-off:
-
Pros: It provides the familiar Kotlin
mapOfsyntax, making code significantly concise for flat structures. -
Cons: It relies on runtime type checking. Passing an unsupported type (e.g.,
Dateor a custom class) will not be caught by the compiler and will result in a runtime exception (or explicit error) inside the factory function.
Is this trade-off acceptable for the sake of providing idiomatic Kotlin Syntax? Or should we strictly stick to the Type-Safe Builder DSL (buildWritableMap) to prevent runtime crashes?
In My opinion: Both should be provided—Builders for complex/safe logic, Factories for simple/quick initialization.
Please share your thoughts! Feedback on API shape, scope, or anything else is very welcome.