Funciones en TypeScript

Las funciones en TypeScript guardan una sintaxis muy similar a la empleada en ES6 y retrocompatible con JS5. Si bien el código final dependerá de la versión de JavaScript que tengamos determinada en nuestro archivo tsconfig.json (lo que, a su vez, viene determinado por el público target al que nos dirigimos), en ambos casos la transpilación generará las funciones de forma que sean totalmente compatibles.

Con carácter general, TypeScript permite definir tres tipos de funciones:

  • Funciones con nombre.
  • Funciones anónimas.
  • Funciones lambda.

Hay quien habla de un cuarto tipo, que son los métodos. Esta no es más que una cuestión semántica para referirnos a funciones dentro del contexto de clases. En todo caso, los métodos pueden ser de cualquiera de los tipos mencionados anteriormente. De los métodos hablaremos en los artículos que dediquemos a clases y objetos. En este, conoceremos los tres tipos de funciones que he mencionado, y que no son si no distintas sintaxis para escribir funciones (entiendo que si conoces JavaScript, el concepto de «función» lo tienes más que asumido). Además, al final de este artículo conoceremos un par de peculiaridades de los parámetros de funciones en TypeScript.

FUNCIONES CON NOMBRE

Aquí estamos ante la declaración típica de un función «de las de toda la vida». Simplemente, se declara como se ha hecho siempre en JavaScript, con la palabra reservada function, seguida del nombre de la función. La única diferencia es que, como ya sabemos, TypeScript nos permite establecer el tipo de datos, y es algo que deberemos hacer a la hora de establecer los parámetros que recibe la función y el retorno, si es el caso. Este tipo de funciones no tienen nada de particular. Tienes un código de ejemplo en funciones_con_nombre_1.ts, en el paquete de códigos de este artículo, por si quieres echarle un vistazo. No lo reproduzco aquí porque ocupa su sitio y, como hemos comentado, no aporta nada nuevo.

También podemos emplear una sintaxis alternativa, que lo que hace es crear un elemento y asignarle, como contenido, una función. Tienes un ejemplo en el código funciones_con_nombre_2.ts. La función se sigue invocando por su nombre (el del elemento que hemos creado al efecto) y su operativa es la misma que en caso anterior.

Escoger una manera de declarar las funciones u otra es una cuaestión de criterio personal.

FUNCIONES ANÓNIMAS

Estas son las funciones que se asignan, directamente, como respuesta a un evento. No tienen un nombre, por lo que no pueden ser invocadas posteriormente desde ninguna parte del documento. Solo se disparan si se detecta el evento. Tienes un ejemplo que se dispara a la carga de la página, en funciones_anonimas.ts. Es una forma muy cómoda de declarar funciones para determinados eventos pero, como sabes, los posibles eventos están bastante limitados. Hay determinados elementos sobre los que no se pueden registrar eventos en JavaScript. Por ejemplo, las colecciones de elementos (algo así como document.getElementsByTagName("input")) no detentan eventos de forma individualizada, por lo que no se puede emplear este tipo de declaraciones de funciones sobre dichas colecciones (a menos, claro, que recurras a herramientas como jQuery).

Normalmente, estas funciones se emplean para eventos globales como la carga de la página en la ventana, o el reescalado de esta.

FUNCIONES LAMBDA

También llamadas coloquialmente con el nombre de «funciones de flecha gorda» son, realmente, las mismas funciones, con una notación diferente, sin emplear la palabra reservada function. Esto puede inducir a confusión, cuando ves el código, por lo que las mencionamos aquí para que sepamos «de que va». Personalmente, no soy partidario de esta notación, pero te la he incluido en un ejemplo en los listados, para que la veas y juegues con ella. El listado se llama funciones_lambda.ts.

ERRORES Y HORRORES

Durante la transpilación de estos códigos te vas a encontrar con tantos mensajes de error del transpilador que, seguramente, pienses que «algo está mal». No te asustes. Ya nos hemos enfrentado anteriormente a estas situaciones. Aunque el transpilador te habla de un error, en realidad es sólo una advertencia que, si tu código está correcto, no te va a dar ningún problema. En concreto, los supuestos «errores» que vas a encontrar aquí son de dos tipos:

ts/funciones_con_nombre_1.ts(4,5): error TS2531: Object is possibly 'null'.

Te avisa de que un objeto determinado es «probablemente» de tipo null. Realmente, lo que hace esto es llamar tu atención para que, si te refieres a un objeto, estés seguro de que el mismo existe en el documento. Si, por ejemplo, te has equivocado al asignarle el valor al atributo id, tu JavaScript transpilado lanzará un error en tiempo de ejecución, por no encontrar el objeto. Si tus identificadores están correctamente asignados, no habrá ningún problema.

El otro aviso que vas a encontrar es como el siguiente:

ts/funciones_con_nombre_1.ts(4,43): error TS2339: Property 'value' does not exist on type 'HTMLElement'.

Puedes ignorarlo directamente. Este aviso se lanza porque, a priori, existen elementos HTML que no tienen la propiedad value. Sin embargo, cómo en estos ejemplos la estamos usando sobre elementos que si la tienen, esto no te dará tampoco ningún problema.

Y sí. Como vamos viendo, el transpilador es extremadamente conservador en cuanto al número de avisos que da pero, como ves, la mayoría no son errores.

PARÁMETROS POR DEFECTO, OPCIONALES Y MÚLTIPLES

A los parámetros de una función se les pueden asignar valores por defecto, de forma que si la función es invocada sin recibir un parámetro concreto, se le asigne el valor por defecto especificado en la declaración de la misma. Tienes un ejemplo en parametros_por_defecto.ts.

Los parámetros pueden ser opcionales, es decir, que se le pasen a la función en el momento de llamarla, o que no se le pasen. Esto, que muchos presentan como una novedad de TypeScript es, en realidad, el comportamiento de JavaScript de toda la vida. Si no pasas un parámetro, dentro de la función este se asumirá con el valor undefined. Lo que se hace en TypeScript es marcar, en la declaración, los parámetros opcionales con el signo ?, así:

function opcional(parametro?:string)

Esto no modifica el comportamiento de la función. Aún tienes que seguir comprobando en el interior si el valor del parámetro es undefined. De hecho, al transpilar, verás que no hay diferencia en el JavaScript si pones el signo ? o no lo pones. Entonces, ¿por qué ponerlo? Es una cuestión semántica, un convencionalismo adoptado para indicar que ese parámetro es opcional, es decir, que puede haber llamadas a la función que lo incluyan, y otras que no.

Por último, cuando se declara una función, puede que alguno de los parámetros que reciba sea una matriz, en lugar de un valor simple. Tienes un ejemplo en parametros_multiples.ts. En ese caso tenemos dos posibles formas de declarar el parámetro que es una matriz. La primera es la siguiente:

function multiples(color:string, ...banderas:string[])

Los tres puntos tienen una finalidad semántica, para indicar que el argumento debe ser una matriz. Declarándolo así, si queremos iterar la matriz deberemos referirnos a su primer elemento (el [0]), que es donde queda encapsulado el contenido real de la matriz. Lo haríamos así:

for (let bandera of banderas[0])

La alternativa es declarar la función sin preceder la matriz de los tres puntos, así:

function multiples(color:string, banderas:string[])

En ese caso, el acceso a la matriz es directo, así:

for (let bandera of banderas)

Usar una notación u otra es cuestión de elección personal, pero las notaciones semánticas ayudan mucho cuando se trata de trabajar con códigos grandes, con muchas líneas y variables, de forma que nos facilite saber lo qué es cada cosa.

CONCLUYENDO

Si conoces ES6 (JavaScript 2015) verás que en este artículo no hemos visto nada nuevo. Salvo el tipado de datos, todo lo que hay aquí es solo para que veas que las funciones se siguen empleando del mismo modo. La única razón para emplear TypeScript, en lo que a funciones se refiere, es que lo uses en todo tu proyecto, principalmente por el tipado de datos. Los códigos de ejemplos de este arttículo, que no he incluido en el texto por no hacerlo demasiado extenso, están en este enlace.

   

Deja un comentario