Ejemplo (3): haciendo las funciones de control de datos

Con los JSONs que importamos en nuestra aplicación en el primer capítulo, vamos a hacer un par de funciones que nos permitan recuperar información de los catálogos, que será la que luego sirvamos en la aplicación.

Para manipular datos JSON con seguridad y claridad en TypeScript, lo primero que debemos hacer es definir tipos personalizados que representen la estructura de esos datos. Aunque TypeScript cuenta con un sistema de inferencia bastante potente que puede deducir tipos al importar un JSON, crear manualmente nuestras interfaces nos permite entender mejor el proceso y controlar con precisión cómo trabajamos con esos datos.

Empezamos definiendo una interfaz para representar un club. Esta interfaz incluye un nombre de tipo string, un código que puede ser string o null, y un país también como string. Así, tenemos una estructura clara para cada club dentro de nuestro sistema.

export interface Club {
  name: string;
  code: string | null;
  country: string;
}

Luego, definimos otra interfaz para agrupar estos clubes bajo un nombre general, que también es un string, y un array de clubes.

export interface Clubs {
  name: string;
  clubs: Club[];
}

Cuando pasamos a los resultados de partidos, la estructura es un poco más compleja. Tenemos un nombre general y un array de partidos, donde cada partido contiene información como la ronda, la fecha (como string), los dos equipos participantes y, opcionalmente, un marcador. Este marcador es un objeto que incluye un campo llamado ft, que es una tupla con dos números, representando el resultado final.

export interface Match {
  round: string;
  date: string;
  team1: string;
  team2: string;
  score?: {
    ft: [number, number];
  };
}

export interface Matches {
  name: string;
  matches: Match[];
}

Con estas interfaces definidas, podemos cargar nuestros archivos JSON y tiparlos adecuadamente. Por ejemplo, al importar clubs.json, lo tipamos como Clubs, y al importar results.json, como Matches. Es importante recordar que TypeScript no valida en tiempo de ejecución que los datos realmente coincidan con estos tipos; simplemente asume que son correctos. Por eso, si los datos no cumplen con la estructura esperada, el programa puede fallar en ejecución.

Para trabajar con estos datos, creamos funciones que nos permitan buscar información específica. Por ejemplo, una función getClub que recibe un código de equipo y devuelve el objeto Club correspondiente. Utilizamos el método find de los arrays para buscar el club cuyo código coincida con el proporcionado.

function getClub(code: string): Club {
  const club = clubs.clubs.find(club => club.code === code);
  if (!club) {
    throw new Error(`No existe este equipo: ${code}`);
  }
  return club;
}

Aquí, añadimos una comprobación para lanzar un error si no se encuentra ningún club con ese código, evitando así devolver un valor undefined que podría causar problemas más adelante.

De manera similar, para obtener un partido entre dos equipos, creamos una función que recibe los nombres de ambos equipos y busca en el array de partidos un encuentro que coincida con esos equipos. Si no se encuentra, también lanzamos un error.

function getMatch(eq1: string, eq2: string): Match {
  const match = results.matches.find(
    match => match.team1 === eq1 && match.team2 === eq2
  );
  if (!match) {
    throw new Error(`No existe este partido este año: ${eq1} vs ${eq2}`);
  }
  return match;
}

Aunque estas funciones son sencillas y utilizan programación funcional con métodos de arrays, debemos tener en cuenta que su rendimiento puede no ser óptimo para grandes volúmenes de datos, ya que la búsqueda es lineal. Para mejorar esto, podríamos considerar estructuras de datos más eficientes como mapas o tablas hash, pero para fines didácticos y simplicidad, esta aproximación es suficiente.

Finalmente, estas funciones pueden integrarse en un servidor web para responder a peticiones que soliciten información sobre equipos o partidos, proporcionando así una API sencilla y segura basada en tipos bien definidos.

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