← React & TypeScript

Reto de código

implementa estas tres utilidades con los tipos correctos (sin usar any):

Reto: implementa estas tres utilidades con los tipos correctos (sin usar any):

1. primerElemento(arr) — devuelve el primer elemento o undefined si está vacío.
2. extraerPropiedad(obj, clave) — devuelve obj[clave], y la clave debe existir en obj.
3. agruparPor(arr, obtenerClave) — agrupa los elementos según la clave que devuelve la función.

Tests: utilidades-genericas.test.ts — intenta resolverlo antes de leer la solución de abajo.
Ver solución
// Reto: implementa estas tres utilidades con los tipos correctos (sin usar any):
//
// 1. primerElemento(arr) — devuelve el primer elemento o undefined si está vacío.
// 2. extraerPropiedad(obj, clave) — devuelve obj[clave], y la clave debe existir en obj.
// 3. agruparPor(arr, obtenerClave) — agrupa los elementos según la clave que devuelve la función.
//
// Tests: utilidades-genericas.test.ts — intenta resolverlo antes de leer la solución de abajo.

// <T> es un genérico: la función funciona con cualquier tipo,
// pero TypeScript conserva la relación entrada → salida.
// Con number[] devuelve number | undefined; con string[], string | undefined.
export function primerElemento<T>(arr: T[]): T | undefined {
  return arr[0];
}

// K extends keyof T restringe la clave a las propiedades reales de T.
// El tipo de retorno T[K] es exacto: extraerPropiedad(persona, "edad") es number.
export function extraerPropiedad<T, K extends keyof T>(obj: T, clave: K): T[K] {
  return obj[clave];
}

// Combina genéricos con Record: la salida es un objeto cuyas claves
// son las que produce obtenerClave, y cuyos valores son arreglos de T.
export function agruparPor<T, K extends string>(
  arr: T[],
  obtenerClave: (item: T) => K
): Record<K, T[]> {
  const grupos = {} as Record<K, T[]>;
  for (const item of arr) {
    const clave = obtenerClave(item);
    if (!grupos[clave]) {
      grupos[clave] = [];
    }
    grupos[clave].push(item);
  }
  return grupos;
}