Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. TypeScript
Code

TypeScript para Principiantes, Parte 5: Genéricos

by
Difficulty:IntermediateLength:MediumLanguages:
This post is part of a series called TypeScript for Beginners.
TypeScript for Beginners, Part 4: Classes

Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)

El segundo tutorial en nuestra serie TypeScript para Principiantes se centró en tipos de datos básico disponibles en TypeScript. La revisión de tipo en TypeScript nos permite asegurar que las variables en nuestro código solo pueden tener tipos específicos de valores asignados a estas. De esta manera podemos evitar muchos errores mientras escribimos código debido a que el IDE será capaz de decirnos cuando estamos realizando una operación sobre un tipo que no soporta. Esto hace a la revisión de tipo una de las mejores características de TypeScript.

En este tutorial, nos centraremos en otra importante característica de este lenguaje---genéricos. Con genéricos, TypeScript te permite escribir código que puede actuar sobre una variedad de datos en vez de ser limitado a solo uno. Aprenderás sobre la necesidad de genéricos a detalle y cómo es mejor que solo usar el tipo de dato any disponible en TypeScript.

La Necesidad de Genéricos

Si no estás familiarizado con genéricos, podrías estar preguntándote por qué los necesitamos en absoluto. En esta sección, responderé esta pregunta por ti. Comencemos escribiendo una función que devolverá un elemento aleatorio de un arreglo de números.

La función randomElem que acabamos de definir toma un arreglo de números como su único parámetro. El tipo de retorno de la función también ha sido especificado como un número. Estamos usando la función Math.random() para devolver un número de punto flotante aleatorio entre 0 y 1. Multiplicarlo con la longitud del arreglo y llamando a Math.floor() sobre el resultado nos da un índice aleatorio. Una ves que tenemos el índice aleatorio, devolvemos un elemento en ese índice específico.

Algún tiempo después, digamos que necesitas un elemento aleatorio de cadena de un arreglo de cadenas. En este punto, podrías decidir crear otra función que ataque específicamente cadenas.

¿Qué pasa si necesitas seleccionar un elemento aleatorio de un arreglo de una interfaz que tu definiste? Crear una nueva función cada vez que quieras obtener un elemento aleatorio de un arreglo de diferentes tipos de objetos no es viable.

Una solución para este problema es establecer el parámetro de tipo de arreglo siendo pasado a las funciones como any[]. De este modo, puedes solo escribir la función una vez, y funcionará con un arreglo de todos los tipos.

Como puedes ver, podemos usar la función de arriba para obtener posiciones aleatorias así como colores aleatorios. Un problema mayor con esta solución es que perderás la información sobre el tipo de valor que está siendo devuelto.

Anteriormente, estábamos seguros de que randomPosition sería un número y randomColor sería una cadena. Esto nos ayudó a usar estos valores de manera acorde. Ahora, todo lo que sabemos es que el elemento devuelto podría ser de cualquier tipo. En el código de arriba, podríamos especificar el tipo de randomColor para ser un number y aún así no obtener ningún error.

Una mejor solución para evitar duplicación de código mientras aún conservamos la información de tipo es usar genéricos. Aquí está una función genérica que devuelve elementos aleatorios de un arreglo.

Ahora, obtendré un error si intento cambiar el tipo de randomColor de string a number. Esto prueba que usar genéricos es mucho más seguro que usar el tipo any en tales situaciones.

TypeScript Generics Error

Usando Genéricos Podría Parecer Muy Limitante

La sección previa discutió cómo puedes usar genéricos en vez del tipo any para poder escribir una sola función y evitar sacrificar beneficios de revisión de tipo. Un problema con la función genérica que hemos escrito en la sección previa es que TypeScript no nos dejará realizar muchas operaciones sobre variables pasadas a esta.

Esto es porque TypeScript no puede hacer ninguna suposición sobre el tipo de variable que será pasada a nuestra función genérica de antemano. Como resultado, una función genérica solo puede usar aquellas operaciones que son aplicables en todos los tipos de datos. El siguiente ejemplo debería hacer este concepto más claro.

La función de arriba removerá todas las ocurrencias del caracter especificado desde la cadena dada. Podrías querer crear una versión genérica de esta función para que también puedas remover dígitos específicos de un número dado así como caracteres de una cadena. Aquí está la función genérica correspondiente.

La función removeChar no te mostró un error. Sin embargo, si usas replace dentro de removeIt, TypeScript te dirá que replace no existe para el tipo 'T'. Esto es debido a que TypeScript ya no puede asumir que theInput va a ser una cadena.

Esa restricción sobre usar diferentes métodos en una función genérica podría llevarte a pensar que el concepto de genéricos no va a ser de mucha utilidad después de todo. Eso no es realmente mucho cuando puedes hacerlo con un puñado de métodos que deben ser aplicables en todos los tipos de datos para que los uses dentro de una función genérica.

Una cosa importante que deberías recordar en este punto es que no creas generalmente funciones que serán usadas con todos los tipos de datos. Es mucho más común crear una función que será usada con un conjunto específico o rango de tipos de datos. Esta restricción sobre tipos de datos hace a las funciones genéricas mucho más útiles.

Crea Funciones Genéricas Usando Restricciones

La función genérica removeIt de la sección anterior mostró un error porque el método replace dentro de esta debe ser usado con cadenas, mientras que los parámetros pasados a este podría tener cualquier tipo de dato.

Puedes usar la palabra clave extends para restringir los tipos de datos que son pasados a una función genérica en TypeScript. Sin embargo, extends está limitado a solo interfaces y clases. Esto significa que la mayoría de funciones genéricas que creas tendrán parámetros que extienden una interfaz o clase base.

Aquí está la función genérica que imprime el nombre de la gente, familiares o celebridades pasados a esta.

En el ejemplo de abajo, hemos definido tres interfaces, y cada una de ellas tiene una propiedad name. La función genérica printName que creamos aceptará cualquier objeto que extienda a People. En otras palabras, puedes pasar ya sea un objeto de familiar o celebridad a esta función, e imprimirá su nombre sin ninguna queja. Puedes definir muchas más interfaces, y mientras tengan una propiedad name, podrás usar la función printName sin ningún problema.

Este fue un ejemplo muy básico, pero puedes crear más funciones genéricas útiles una vez que estés más cómodo con todo el proceso. Por ejemplo, puedes crear una función genérica que calcule el valor total de diferentes artículos vendidos en un mes dado siempre y cuando cada artículo tenga una propiedad price para almacenar el precio y una propiedad sold que almacene el número de artículos vendidos. Usando genéricos, podrás usar la misma función siempre que los elementos extiendan la misma interfaz o clase.

Ideas Finales

En este tutorial, he intentado cubrir los básicos de genéricos en TypeScript de manera amigable con principiantes. Comenzamos el artículo discutiendo la necesidad de genéricos. Después de eso, aprendimos sobre la manera correcta de usar genéricos para evitar duplicación de código sin sacrificar la disponibilidad de revisión de tipo. Una vez que entiendas los básicos discutidos aquí, puedes leer más sobre genéricos en la documentación oficial.

Si tienes preguntas relacionadas a este tutorial, estaré feliz de responderlas en los comentarios.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.