Entender las advertencias del modo estricto

Entender las advertencias del modo estricto

> Tutorial de LeekScript

Has decidido pasar al modo estricto, y el editor te inunda de múltiples advertencias que antes no existían. Que no cunda el pánico: precisamente el interés del modo estricto es ser menos permisivo y dejar menos libertad, sobre todo en el tipado. Veamos algunos casos frecuentes de advertencias, para entender primero cuál es el problema señalado y encontrar soluciones para remediarlo.

Conversión peligrosa del tipo « real » al tipo « integer »

Un primer caso sencillo: quiero guardar el resultado de un cálculo en una variable de tipo entero.

El problema aquí es que la función sqrt siempre devuelve un valor de tipo real, aunque matemáticamente sqrt(4) valga 2. Ahora bien, un número real no cabe sin pérdida en una variable de tipo entero: ¿qué hacer con los decimales de sqrt(2), por ejemplo? Por eso el compilador pide tomar una decisión explícita. Existen distintas soluciones para resolver esta advertencia:

Conversión peligrosa del tipo « integer? » al tipo « integer »

Otro caso: tengo un array asociativo (Map) de números enteros definido como sigue y quiero guardar un valor de ese array asociativo en una variable de tipo entero también; en principio los tipos deberían coincidir...

¿Por qué la advertencia nos dice que mapEntier[0] es de tipo «integer?» y no simplemente «integer»? Recordemos que el «?» al final de un tipo significa que ese tipo también acepta los valores null; es un equivalente de «integer | null». Entonces, ¿por qué mi array asociativo podría devolverme un valor null, cuando según su tipo solo contiene integer? Cuando se quiere leer un valor de un array asociativo hay que pasarle una clave, aquí «0» entre corchetes; esa clave debe ser del tipo definido en el array asociativo, aquí un integer, así que por ese lado todo va bien. Pero nada garantiza al editor la existencia de la clave en el array asociativo, y si se lee un array asociativo con una clave que no existe, el resultado será siempre null. Por tanto, el resultado de un acceso a un array asociativo por su clave será siempre anulable (nullable). Veamos ahora cómo resolver este problema para dejar de tener alertas:

Conversión peligrosa del tipo « (Array, Function any>) » al tipo « () »

En este caso, tengo una lista de enteros que quiero ordenar; a priori nada muy complejo, incluso retomo el ejemplo de la documentación

Y sin embargo me encuentro con 2 advertencias en esta simple línea. Empecemos por la primera: está rodeada de paréntesis, lo que significa que el problema está en los parámetros de la función, que no respetan la firma esperada. Miremos la documentación de arraySort para ver su firma: Function real | integer> => Array> Es, por tanto, una función que espera 2 parámetros: una lista como primer parámetro, y como segundo parámetro una función que también recibe 2 parámetros y devuelve un entero o un real. Como primer parámetro sí le pasamos una lista, ningún problema por ahí; así que es en el segundo parámetro donde algo no va: pasamos una función con la firma Function any>, mientras que arraySort espera Function real | integer>; el tipo de retorno no es el esperado.

El problema de tipado de la función de callback está resuelto; queda ahora la segunda advertencia. Como acabamos de ver, el retorno de la función arraySort no es un Array\ como esperamos para nuestra variable, sino simplemente Array, así que hay que convertir (cast) el retorno explícitamente para corregir este problema.