Funciones: tipando funciones

Todos los tipos que tenemos para tipar funciones, y haciendo ejemplos más complejos de funciones para demostrar la flexibilidad de su sistema de tipos. Por ejemplo, ¿quieres hacer una función arrow? Tipable. ¿necesitas que tu función acepte como parámetro una función de callback? Tipable.

Las funciones en TypeScript son mucho más que simples bloques de código; son elementos de primera clase, lo que significa que podemos tratarlas como cualquier otra variable o dato. Esto nos permite asignar funciones a variables, pasarlas como argumentos y devolverlas desde otras funciones, lo que abre un abanico enorme de posibilidades para escribir código flexible y reutilizable.

Cuando declaramos una función con un nombre, como sumar, le estamos asignando un identificador con un tipo específico que representa esa función. Pero también podemos crear funciones anónimas y asignarlas directamente a variables. Por ejemplo, podemos declarar una variable llamada restar y asignarle una función que reciba dos parámetros de tipo number y devuelva su resta:

const restar = function(m: number, n: number): number {
  console.log('Ejecutando resta');
  return m - n;
};

console.log(restar(5, 4)); // 1

Aquí, TypeScript infiere el tipo de restar como una función que recibe dos números y devuelve un número. Para que quede más claro, podemos declarar explícitamente el tipo de la variable restar:

const restar: (m: number, n: number) => number = function(m, n) {
  console.log('Ejecutando resta');
  return m - n;
};

Esta sintaxis, aunque un poco particular, es muy común cuando trabajamos con funciones que reciben otras funciones como parámetros, como los callbacks. Por ejemplo, podemos declarar una función multiplicar con un tipo específico, pero sin asignarle inmediatamente una implementación:

let multiplicar: (m: number, n: number) => number;

Luego, podemos asignarle una función sin necesidad de volver a especificar los tipos de los parámetros, ya que TypeScript los infiere automáticamente:

multiplicar = function(m, n) {
  return m * n;
};

console.log(multiplicar(4, 3)); // 12

También podemos usar la sintaxis de arrow functions para hacer el código más conciso:

multiplicar = (m, n) => m * n;

Esta capacidad de inferencia es especialmente útil cuando trabajamos con callbacks. Por ejemplo, imaginemos que queremos crear una función que reciba dos números y una función callback que procese el resultado de multiplicarlos. Podríamos definirla así:

function multiplicarConCallback(
  a: number,
  b: number,
  callback: (result: number) => void
): void {
  const resultado = a * b;
  callback(resultado);
}

Al llamar a esta función, podemos pasarle una función anónima que reciba el resultado y lo imprima:

multiplicarConCallback(4, 5, (resultado) => {
  console.log(`El resultado es ${resultado}`);
});

En este ejemplo, TypeScript sabe que el parámetro resultado dentro del callback es un number, por lo que podemos usar métodos propios de los números, como toFixed o toExponential, con autocompletado y chequeo de tipos.

Este enfoque de tipar funciones que reciben otras funciones como parámetros es muy común en librerías y frameworks, especialmente en aquellas que manejan eventos o código asíncrono. Nos permite escribir código seguro y claro, donde los tipos de los argumentos y retornos están bien definidos y el autocompletado nos ayuda a evitar errores.

Así, TypeScript nos ofrece una forma poderosa y flexible de trabajar con funciones, combinando la libertad de JavaScript con la seguridad y claridad que aporta la tipificación estática.

Lista de reproducción
  1. 1
    Temporada 1
    5 minutos
  2. 2
    ¿Qué es TypeScript?
    11 minutos
  3. 3
    Instalando TypeScript
    8 minutos
  4. 4
    Compilando un Hola Mundo sencillo
    7 minutos
  5. 5
    Hola Mundo pero con tipos
    10 minutos
  6. 6
    Tipos: tipos primitivos
    12 minutos
  7. 7
    Tipos: tipos especiales (any, null, ...)
    10 minutos
  8. 8
    Tipos: arrays y tuplas
    11 minutos
  9. 9
    Tipos: objetos
    7 minutos
  10. 10
    Funciones: lo básico
    9 minutos
  11. 11
    Funciones: tipando funciones
    9 minutos
  12. 12
    Clases: introducción a las clases
    9 minutos
  13. 13
    Clases: creando una clase
    10 minutos
  14. 14
    Clases: modificador private
    8 minutos
  15. 15
    Clases: modificador readonly
    3 minutos
  16. 16
    Clases: Atributos virtuales con getters y setters
    10 minutos
  17. 17
    Clases: herencia
    9 minutos
  18. 18
    Clases: modificadores abstract y protected
    8 minutos
  19. 19
    Tipos alias
    6 minutos
  20. 20
    Tipos literales
    5 minutos
  21. 21
    Uniones de tipos
    7 minutos
  22. 22
    Uniones discriminantes
    7 minutos
  23. 23
    Intersecciones de tipos
    5 minutos
  24. 24
    Interfaces: introducción
    7 minutos
  25. 25
    Interfaces: modificadores y funciones
    9 minutos
  26. 26
    Interfaces: usándolas con clases
    8 minutos
  27. 27
    Interfaces: herencia de interfaces
    8 minutos
  28. 28
    Interfaces: interfaces indizadas
    5 minutos
  29. 29
    Interfaces: funciones y tipos híbridos
    5 minutos
  30. 30
    ¿Qué diferencia hay entre interfaces y tipos? (2020)
    8 minutos
  31. 31
    Casteos con as
    6 minutos
  32. 32
    instanceof y las guardas
    9 minutos
  33. 33
    Tipos enumerados
    8 minutos
  34. 34
    Valores avanzados para enumerados
    7 minutos
  35. 35
    Enumerados con valores computados
    6 minutos
  36. 36
    Genéricos en tipos
    8 minutos
  37. 37
    Múltiples genéricos y buenas prácticas
    5 minutos
  38. 38
    Genéricos en funciones
    8 minutos
  39. 39
    Genéricos con restricciones
    6 minutos
  40. 40
    Tipos de utilidad
    3 minutos
  41. 41
    Exportando módulos
    9 minutos
  42. 42
    Importando módulos
    7 minutos
  43. 43
    Export default e import asterisco
    6 minutos
  44. 44
    tsconfig
    7 minutos
  45. 45
    Módulos desde NPM
    7 minutos
  46. 46
    Arroba types y los .d.ts
    8 minutos
  47. 47
    Ejemplo (1): creando una API REST simple en TypeScript
    11 minutos
  48. 48
    Ejemplo (2): montando un servidor Express
    8 minutos
  49. 49
    Ejemplo (3): haciendo las funciones de control de datos
    11 minutos
  50. 50
    Ejemplo (4): conectando todas las piezas
    7 minutos