• slidebg1

Tipando fuerte: Javascript con tipado seguro


Parte I: Reconocimiento del terreno + nuestra primera herramienta

Los que hayan desarrollado o conozcan javascript, pronto se dan cuenta de lo poco que pegan las palabras javascript y tipado fuerte.

Bien, esto es natural, ya que javascript ha nacido con tipado dinámico, es decir, no hace falta que especifiquemos en el código de que tipo va a ser cada variable, el compilador se lo va asignar en tiempo de ejecución.

Siempre que aludo al tipado dinámico, me gusta hacer referencia a un concepto conocido como duck typing el cual, se podría decir, que se  conmemora con la siguiente afirmación:

“Si veo un ave que, camina como un pato, parpa como un pato, y nada como un pato, yo a ese ave le llamo Pato”

 

Frase atribuida a James Whitcomb Riley escritor y poeta.

Una síntesis magnífica de cómo actúa el compilador a la hora de asignar el tipo a las variables.

Puede que te preguntes lo siguiente. Si el compilador ya hace este trabajo por mí ¿Por qué me iba a interesar hacer este trabajo manualmente?

Buena pregunta, teniendo en cuenta la proliferación de aplicaciones web basadas en JS, HTML y CSS y los numerosos avances en estas tecnologías, pongamos el siguiente caso:

En una aplicación en la que, por ejemplo, tengas que comunicarte con un servidor, enviando y recibiendo datos…

Que menos por parte del front-end, asegurarnos de que si le envío un boolean || string || number… que efectivamente sea un boolean || string || number. Conservando así la integridad de los datos.

O bien, cuando reciba datos por parte del back-end, asegurarme de que el tipo de dato que recibo es el esperado, y de esa forma estar seguros de que el comportamiento de nuestro código es el esperado, sin llevarme desagradables sorpresas. Asegurando el correcto funcionamiento de nuestra aplicación web 

Hemos puesto un ejemplo de cómo utilizar el tipado seguro para garantizar la integridad de nuestros datos y de nuestra aplicación, pero a parte de esto, también se le puede sacar mucho partido al hecho de conocer el tipo de dato con el que se está tratando.

Por ejemplo, establecer diferentes comportamientos en función del tipo de dato que reciba, es decir, sobrecarga de métodos

Para concluir la presentación, este post no tiene como objetivo determinar con que es mejor trabajar, si con tipado dinámico o con tipado fuerte, todo lo contrario.

El objetivo de este post es, mostrar cómo, trabajar con ambas formas, no solo es muy posible, si no que a parte Muy útil

Porque conocer el tipo de dato que tiene una variable en un determinado momento y entender de qué forma trabajar con ello, nos acerca mucho a entender cómo funcionan los lenguajes con tipado dinámico, y como consecuencia directa, nos hace mejorar la calidad y robustez de nuestro código 

Concluida la presentación…

Pongamos código a este concepto!

Estructuras de datos en javascript

consultalo de primera mano aquí 

Ahora veremos qué recursos nos proporciona javascript ¿Para qué? Para conocer el tipo de dato concreto que contiene una variable. 

Pero antes de empezar, vayamos a las bases con un poco de teoría.

Javascript, como casi todos los lenguajes de programación, diferencia dos categorías de datos, primitivos y complejos u objetos.

Javascript cuenta con 6 tipos de datos primitivos, 7 si contamos el nuevo introducido en el ECMAScript 6 Symbol, estos son:

1) string

2) boolean

3) number

4) null

5) undefined

6) object 

7) Symbol //ES6

Confío en que los tres primeros no te hagan fruncir el ceño.

Sobre el resto vamos a hablar ahora, sobre todo, porque para llevar a cabo lo que nos proponemos de una forma coherente y satisfactoria, hace falta una buena y clara base teórica. 

null

Significado  Valor vacío

No tiene mucho más, aunque es importante entender la diferencia entre null y undefined del cual vamos a hablar ahora. 

Un pequeño apunte sobre este tipo de valor.

Actualmente si le preguntas a javascript que tipo de dato es null, no te responde que es null, te responde  que es object, esto es considerado como un bug, pero bueno, yo prefiero verlo como una peculiaridad, más que como un error.

undefined

Significado  Valor no asignado OJO no confundir con null, valor vacío

No te compliques mucho con este tipo de dato, simplemente entiende lo que significa, referencia que indica que no existe ningún valor asignado.

Este valor se asigna automáticamente por el compilador cuando recorre un contexto de ejecuciónbuscando y situando todas las variables y referencias, asignándoles en primera instancia el valor undefined. Esto se conoce como hoisting. Pero no es el objetivo de este post profundizar sobre este tipo de conceptos. Siéntete libre de investigarlos por tu cuenta.

Una recomendación, nunca iguales el valor de una variable a undefined porque de hecho puedes, sin embargo, puede que te veas en la situación de no saber si el valor es undefined por haberla igualado o porque algo no anda bien en tu código, lo cual se traduce en… muchas horas de debugging, mejor utiliza null, ya que esa es su función principal

object

Significado variable que contiene un tipo de dato complejo.

Simple, solo nos informa de que el contenido de esa variable es de tipo complejo y para eso utiliza el tipo primitivo object, parece tonto, pero esto nos va a ser muy útil en nuestro propósito

Eso sí, no confundamos object con Object el primero es un tipo primitivo y el segundo un tipo complejo. Más adelante lo explicaremos mejor.

Symbol

Significado  Valor inmutable e único.

No vamos a entrar en mucho detalle con este tipo de dato, como hemos dicho, es un tipo de dato inmutable e único, lo que quiere decir que, una instancia de Symbol sólo es igual a la misma instancia de Symbol. (Si has desarrollado en java, rápidamente lo relacionamos con los Enums)

Después de este repaso, ya podemos empezar a introducir los siguientes conceptos. 

Herramientas para obtener el tipo en javascript

typeof

Nuestra primera herramienta, su nombre es bastante claro, “El tipo de...” Sugiere que le demos algo ¿Una variable tal vez? Bueno para ser más concretos un dato, aunque no esté en forma de variable.

Javascript Code: testing typeof I

 

Como vemos, su funcionamiento es simple, no tiene mucha ciencia, le doy un dato y me devuelve, en forma de cadena, el tipo de dato que contiene.

Parece que ya tenemos solucionado nuestros problemas ¿no? Bueno, antes de cantar victoria, investiguemos más sobre esta herramienta.

Probemos cómo se comporta cuando en vez de tipos primitivos, le doy un  valor de tipo complejo.

Javascript Code: testing typeof II

 

Como vemos, nos está devolviendo únicamente el tipo primitivo object

Bueno, hace nada hemos hablado del tipo de valor object, recordemos su definición:

“Variable que contiene un tipo de dato complejo”

De esto podemos concluir que lo que nos dice typeof es que eso es un objeto, pero no nos puede dar más información sobre él.

También podemos deducir que typeof solo puede trabajar con estructuras de datos primitivas.

Bueno, aunque parezca que es poco, esto es mucho, ya nos está diciendo algo importante, nos dice de qué forma debemos tratarlo. Y con esto hemos finalizado con typeof y continuamos con nuestra siguiente herramienta. 

instanceof

Con la herramienta anterior nos topamos con un muro, cuando el valor se trataba de un tipo complejo, únicamente nos devolvía que se trataba de un object, pero este muro se derriba gracias a instanceof

Su funcionamiento es un poco diferente, requiere de dos parámetros

 

El primero, como sufijo…

La instancia de un objeto, que gracias a typeof ya se como identificar.

El segundo, como prefijo…

El tipo con el que lo quieres comparar.

Y de valor de vuelta, un booleano que…

Nos está afirmando si el valor que le has pasado es o no del tipo con el que lo estas comparando.

Vemos en un ejemplo, como funciona.

Javascript Code: Testing instanceof

Vaya ahora parece que ya hemos solucionado nuestro problema con los objetos, ya podemos saber si la variable que le estamos pasando contiene o no el tipo que esperábamos.

Sin embargo, esta herramienta no me proporciona algo que typeof si. Que es, el nombre del tipo del valor. Tan solo podemos comparar dos instancias, vaya… y si lo que quiero saber es de qué tipo es ¿Qué hacemos? ¿Probarlo con todos los tipos, los nativos y los que haya podido crear yo en mi código?

No parece una solución aceptable...

Aunque, para poder dar respuesta a la pregunta, considero conveniente  hacer otra pequeña parada teórica, esta vez acerca de los objetos y javascript.

Confía en mí, esto te va a ser muy útil.

Empecemos por puntualizar que javascript es un lenguaje basado en prototipos, lo que significa que...

No tiene clases! Vaya, bueno… ¿Tanta diferencia supone?

Pues resulta que el tipo que determina a un objeto viene dado por el nombre de su clase, cosa que javascript, no tiene.

Pero, si hace un momento acabamos de utilizar, el tipo Date, para compararlo con otro objeto.

 

Javascript Code:  remembering...

Si, no hay duda, lo acabamos de utilizar, y además tiene toda la pinta de un tipo… Pero ¿Qué es realmente?

Javascript Code: researching...

Una función! por lo que ¿Que está ocurriendo?

Pues resulta que al no existir clases, está utilizando la función Date a modo de plantilla o prototipo y de este modo, declarar un objeto en base a esa función.

También podemos observar que el objeto today tiene dentro un atributo llamado constructor

Y que el contenido de este mismo atributo es igual al de Date que es una función.

Bueno pues resulta que Date es la función constructora del objeto today. Creo que ya va cogiendo algo más de sentido ¿Cierto?

Aunque me encantaría continuar hablando sobre los objetos y javascript, si quieres saber, tendrás que investigarpor tu cuenta.

Pero antes de finalizar un pequeño apunte, independientemente de la nueva implementación que viene en el ES6 que permite usar el literal reservado “class” javascript sigue sin tener clases, es tan solo, syntactic sugar. 

Construyendo nuestra primera herramienta

Bueno, ahora que ya sabemos bastante acerca de los tipos en javascript y de cómo utilizarlos, o al menos lo suficiente

Podríamos construirnos una pequeña herramienta para saber y controlar con qué tipo estoy trabajando.

Te propongo el reto de que lo hagas por ti mismo. Vamos a concretar lo que queremos.

Queremos una herramienta que

  • Unifique el comportamiento de typeof e instanceof

 

  • Que nos sirva para…

○          comprobar si un valor coincide con un tipo

○          devolver cual es el nombre del tipo que contiene el valor

 

  • Y que funcione tanto con tipos primitivos como con tipos complejos

 

Ya hemos visto cómo identificarlos, y sabemos que todos los tipos complejos parten de una función... Así que te daré una pista.

Todas las funciones tienen un atributo llamado “name” que indica su nombre, con lo que hemos hablado antes (tipos complejos -> función constructora)

Además te voy a dejar un ejemplo de cómo debería funcionar, de cómo se vería desde fuera. Más abajo te dejaré mi solución, pero antes de verla, te recomiendo que intentes hacerlo por tu cuenta. Es la mejor forma de comprender todo lo que hemos hablado.

Javascript Code: output of our tool

Bueno, aquí está la solución que he logrado construir, más abajo comento cosas sobre ciertos aspectos del desarrollo de la misma.

Aporte de código  -  type() 

Javascript Code: Our little tool

Para el desarrollo de esta pequeña herramienta, he tenido en cuenta lo siguiente

  • Evitar a toda costa tener que escribir a mano funciones para comprobar cada tipo, o colecciones que guarden los tipos para compararlos.

Ya que sabiendo que, los tipos existen en javascript tan solo tengo que saber cómo acceder a ellos, y eso, ya lo sabemos

Que en este caso sería el equivalente a pasarle los tipos en forma de cadena, ya que realizarlo de esta forma puede dar muchos problemas en el futuro. 

Para el desarrollo de esta herramienta, he contado con…

Todo lo que hemos hablado aquí acerca de los tipos y cómo obtenerlos y compararlos.

También hice una pequeña investigación que me ha llevado a descubrir que existen cuatro funciones constructoras llamadas

String, Boolean, Number y Object, cuyos nombres de función son respectivamente “String”, “Boolean”, “Number” y “Object” 

Solo se diferencian en una mayúscula en comparación con los nombres de los tipos primitivos, así que .toLowerCase() y arreglado! ; ) 

De esta forma hemos unificado todos los tipos ya existentes, y los que puedas desarrollar tu, todo esto sin escribir a mano ningún tipo!

Recuerda que a la hora de desarrollar, ten en cuenta todo lo que el lenguaje tiene que ofrecer, aprovecha todo lo que conoces de él! Y aunque pienses que ya lo conoces suficiente, nunca dejes de investigarlo! 

Conclusión de la primera parte

Como despedida, decir que en este post se han trabajado muchas cosas y que en el siguiente las vamos a ampliar, pero te recomiendo que mientras tanto, trabajes los conceptos que se han visto aquí, y tú mismo te darás cuenta de que no te hace falta esta segunda parte, para concluir la idea que te ha llevado a leer este post.

Este post está inspirado en tres publicaciones de Etnassoft

http://www.etnassoft.com/2016/10/17/tipado-seguro-en-javascript/

http://www.etnassoft.com/2011/08/16/como-obtener-el-tipo-de-datos-preciso-de-una-variable-en-javascript/ 

http://www.etnassoft.com/2011/02/07/duck-typing-en-javascript-chequeando-los-tipos-de-datos/

Excelentes artículos y gran contenido, recomiendo a todos su lectura.

 

 

Públicado el 05/04/2017

Comparte este post:

CATEGORÍAS: Aprendizaje Desarrollo