es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    La razón por la que () -> Unit no se puede convertir a () -> dynamic es porque Unit es un subtipo de Any, pero no un subtipo de dynamic. Por lo tanto, no es seguro convertir una función que devuelve Unit a una función que devuelve dynamic.

    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 tipo Unit, que es un subtipo de dynamic. Por lo tanto, la función lambda se puede convertir de manera segura a () -> dynamic.

    Para escribir f apropiadamente, puedes agregar Unit al final de la función lambda de esta manera:

    val f: () -> dynamic = {
        a = 42
        Unit
    }
    

    Alternativamente, puedes usar la función de extensión toDynamic() proporcionada por la biblioteca kotlin-dynamic de esta manera:

    import kotlin.js.toDynamic
    
    val f: () -> dynamic = {
        a = 42
    }.toDynamic()
    

    Ambos enfoques asegurarán que la función lambda devuelva dynamic y se pueda asignar de manera segura a XMLHttpRequest.onreadystatechange.

Comments are closed.