Comportamiento extraño de lambdas que devuelven `dynamic` en la interoperabilidad de Kotlin/JS.
Quiero escribir una función lambda que devuelve dynamic
y finalice con una operación de asignación. Lo siguiente no pasa la verificación de tipos:
kotlin
var a: Int?
val f: () -> dynamic = {
a = 42
}
Nota: este ejemplo es algo artificial con el propósito de hacerlo lo más mínimo posible. En realidad, necesito asignar esta lambda a XMLHttpRequest.onreadystatechange
, de ahí el requisito de tipos.
f
tiene tipo () -> Unit
cuando se elimina la anotación de tipo. ¿Por qué no se puede convertir () -> Unit
a () -> dynamic
?
Además, ¿cómo es que este ejemplo pasa la verificación de tipos?
kotlin
val f2: () -> dynamic = {
print("foo")
}
f2
sin la anotación también tiene el tipo () -> Unit
. ¿Por qué f2
pasa la verificación de tipos y f
no?
Finalmente, ¿cuál es la forma apropiada de escribir f
? ¿Agregar un Unit
o null
al final, quizás? Eso funciona pero parece bastante feo. ¿Existe una mejor manera de hacerlo?
davy.ai
La razón por la que
() -> Unit
no se puede convertir a() -> dynamic
es porqueUnit
es un subtipo deAny
, pero no un subtipo dedynamic
. Por lo tanto, no es seguro convertir una función que devuelveUnit
a una función que devuelvedynamic
.En el segundo ejemplo,
val f2: () -> dynamic = { print("foo") }
se verifica el tipo porque la expresión dentro del lambda es una expresión de tipoUnit
, que es un subtipo dedynamic
. Por lo tanto, la función lambda se puede convertir de manera segura a() -> dynamic
.Para escribir
f
apropiadamente, puedes agregarUnit
al final de la función lambda de esta manera:Alternativamente, puedes usar la función de extensión
toDynamic()
proporcionada por la bibliotecakotlin-dynamic
de esta manera:Ambos enfoques asegurarán que la función lambda devuelva
dynamic
y se pueda asignar de manera segura aXMLHttpRequest.onreadystatechange
.