typescript-tipos-genericos

Cómo usar tipos genéricos en TypeScript

Los genéricos en TypeScript nos permiten definir funciones, clases o componentes que admiten un tipo como parte de su definición.

De esta forma, pueden comportarse diferente de forma diferente, en función del tipo recibido, adaptando su comportamiento genérico a los diferentes tipos.

Definición de funciones genéricas

Los genéricos se definen utilizando el símbolo < >, y se pueden aplicar tanto a variables como a funciones.

Por ejemplo, podemos crear una función genérica que acepte cualquier tipo de dato:

function imprimirValor<T>(valor: T): void {
    console.log(valor);
}

En este ejemplo,

  • <T> es el tipo genérico que se puede utilizar para representar cualquier tipo de dato.
  • La función imprimirValor acepta un parámetro valor de tipo T y simplemente lo imprime en la consola.

Es muy habitual usar “T” (de “Type”) para denominar al tipo que recibe la función. Pero es posible usar cualquier otra letra o nombre.

Creación de una clase genérica

Además de las funciones, también podemos crear clases genéricas en TypeScript. Esto nos permite crear clases que pueden trabajar con diferentes tipos de datos.

class Coleccion<T> {
    private elementos: T[] = [];

    agregar(elemento: T): void {
        this.elementos.push(elemento);
    }

    obtener(indice: number): T {
        return this.elementos[indice];
    }
}

En este ejemplo,

  • Hemos creado una clase genérica llamada Coleccion que puede almacenar cualquier tipo de dato.
  • La clase tiene un método agregar que acepta un elemento de tipo T y lo añade a una lista interna.
  • También tiene un método obtener que devuelve el elemento en un índice específico.

Restricciones de tipo en genéricos

En ocasiones, es posible que queramos restringir los tipos que se pueden utilizar** con un genérico (por ejemplo, si queremos asegurarnos de que solo se puedan utilizar tipos numéricos con una función genérica)

Podemos lograr esto utilizando restricciones de tipo en los genéricos. Por ejemplo:

function sumarNumeros<T extends number>(a: T, b: T): number {
    return a + b;
}

En este ejemplo,

  • Hemos utilizado la palabra clave extends para indicar que el tipo genérico T debe ser un subtipo de number.
  • Esto nos permite utilizar la función sumarNumeros con cualquier tipo numérico, pero no con otros tipos de datos.

Inferencia de tipos en genéricos

TypeScript tiene la capacidad de inferir automáticamente el tipo genérico en función del tipo de datos proporcionado *(es deicr, que no tenemos que ponerlo nosotros “a mano”)

Esto nos permite escribir código más limpio y conciso sin tener que especificar explícitamente el tipo genérico en cada llamada. Por ejemplo, consideremos la siguiente función genérica:

function imprimirValor<T>(valor: T): void {
    console.log(valor);
}

Si llamamos a esta función sin especificar el tipo genérico:

imprimirValor(42);

TypeScript inferirá automáticamente que el tipo genérico es number, ya que hemos pasado un número como argumento.