Flow: el analizador de tipos de Javascript

Quería aprovechar este post para hablar de Flow, un analizador estático para el lenguaje Javascript, diseñado para detectar posibles errores causados por tipos de variables. Flow es una herramienta de código abierto desarrollada por Facebook que se ejecuta desde la línea de comandos. Está escrita en el lenguaje de programación OCaml y disponible para GNU/Linux y MacOS X.

¿Cómo funciona Flow?

En los lenguajes tipados (tipado fuerte) una variable sólo puede contener valores del tipo con el que fue declarada. Si se asigna un valor de tipo diferente, se genera un error (en tiempo de compilación en el caso de los lenguajes compilados). Por ejemplo, en C#:

int x = 3;
x = "texto";

la asignación de la 2ª línea x = “texto” sería incorrecta (se está asignando una cadena de texto a una variable de tipo entero) y generaría un error en tiempo de compilación. Para asignar un valor a una variable de diferente tipo, es necesario realizar una conversión explícita (mediante métodos u operadores designados a tal efecto).

Sin embargo, como muchos de nuestros lectores sabrán, Javascript es un lenguaje con tipado débil y conversión implícita de tipos. Esto significa que, en Javascript, no se indica el tipo de una variable, sino que éste depende en cada momento del valor que contiene. Esta característica proporciona a los programadores una mayor flexibilidad y facilidad a la hora de desarrollar programas. Sin embargo, tiene la gran desventaja de que puede producir errores difíciles de depurar, provocados por la conversión implícita que realiza el lenguaje al utilizar las variables en asignaciones o expresiones.

Flow es una herramienta que analiza código Javascript y detecta errores de tipos. La gran ventaja de Flow es su capacidad de analizar y detectar errores siguiendo el flujo del programa, incluso aunque no se utilicen anotaciones de tipos.

Primeros pasos con Flow

Para depurar un proyecto Javascript con Flow debemos inicializarlo ejecutando el comando (desde el directorio raíz del proyecto):

flow init

Esto creará un fichero oculto .flowconfig en el directorio actual y nos permitirá utilizar Flow para depurar nuestro proyecto. Para indicar a Flow qué ficheros debe analizar es necesario añadir el siguiente comentario al inicio de dichos ficheros:

/* @flow */

Para analizar los ficheros del proyecto basta con ejecutar el comando:

flow check

Así por ejemplo, si analizamos el siguiente código con Flow:

/* @flow */
 
function mult(x, y) {
return x * y;
}
 
mult(3, "2");

obtendremos el error:

/myproject/mult.js:7:9,11: string
This type is incompatible with /myproject/mult.js:4:10,14: number
 
Found 1 error

que se produce al utilizar una variable de tipo cadena (el segundo argumento de la función mult()) en una operación de multiplicación con un número entero. Este sencillo ejemplo ilustra la capacidad de Flow para seguir el flujo de control del programa (suponemos que de ahí su nombre :-P) e inferir los tipos adecuados para cada variable.

Anotaciones de tipos

Además de seguir el flujo de control del programa, Flow permite utilizar anotaciones de tipos al declarar variables, parámetros de funciones etc. De esta forma podemos escribir la función del ejemplo anterior de la siguiente manera:

/* @flow */
function mult(x: number, y: number): number {
return x * y;
}

Si pasamos una variable con un valor no numérico como parámetro a esta función (por ejemplo una cadena de texto) obtendremos un error similar al mostrado en la sección anterior. En esencia, esta funcionalidad nos permite convertir Javascript en un lenguaje tipado y detectar errores producidos por asignaciones de tipos incorrectas antes de ejecutar el código.

Transformación de ficheros con anotaciones

Obviamente, la definición de tipos no forma parte del lenguaje Javascript y este código no se puede ejecutar directamente. Es decir, es necesario eliminar todas las anotaciones de tipos propias de Flow antes de enviar el código al cliente. Este paso previo de transformación es similar al existente en otros lenguajes que compilan a Javascript como Typescript o Coffescript. Para ello, Flow dispone de una herramienta de transformación incluída en las React Tools, que puede instalarse utilizando npm con el siguiente comando:

npm install -g react-tools

Una vez instalado el paquete, podemos ejecutar el comando jsx indicando la ruta a nuestro proyecto y la ruta en la que queremos que la herramienta deje el código Javascript sin anotaciones. Por ejemplo:

jsx --strip-types --harmony --watch myproject/ build/

Esta herramienta monitorizará en segundo plano el contenido del directorio /myproject y convertirá automáticamente todos los ficheros de Flow a Javascript estándar, dejándolos en el directorio /build. Estos ficheros transformados son los que se deberán servir al cliente para su ejecución.

Transformación de ficheros Flow en el navegador

Una alternativa a la transformación offline de ficheros Flow descrita en la sección anterior es la transformación en el propio navegador. Simplemente basta con incluir un script en nuestra página web y utilizar un tipo MIME especial en los scripts con anotaciones de Flow:

<script src="build/JSXTransformer.js"></script><script type="text/jsx;stripTypes=true;harmony=true">// <![CDATA[ /* @flow */ // ... // ]]></script>

(ejemplo extraído de la documentación oficial)

De esta forma, el navegador ejecutará el script JSXTransformer.js, que eliminará todas las anotaciones de Flow, obteniéndose código Javascript ejecutable. Esta opción sólo es recomendable en entornos de desarrollo debido a las implicaciones en el rendimiento de la página al tener que ejecutar el paso previo de transformación.

Conclusión

Flow es una herramienta muy interesante y seguramente se convertirá en una parte esencial del flujo de trabajo de muchos desarrolladores. Gracias a Flow, es posible analizar programas Javascript, facilitando la depuración y detección de bugs que, de otra manera, pueden ser difíciles de solucionar. Flow es sin duda un gran aporte al ecosistema de Javascript (que es cada vez más rico y extenso) y sigue a otras aportaciones notables de Facebook al mundo open source, tales como HHVM y React.js.

The following two tabs change content below.

Mikel Pintor

Desarrollador web.

Latest posts by Mikel Pintor (see all)

Compartir: