DEV Community

JSmith AR
JSmith AR

Posted on

[ES] TypeScript Sandbox: Función `head`

Esta sera una serie de artículos relacionados con TypeScript en el que tratare de explorar las capacidades de TS al mismo tiempo que algunos conceptos de Programación Funcional.

Función Head

function head(array) {
  if (array.length === 0) throw new Error("array is empty");
  return array[0];
}

head([1, "hello", {}]);
// out: 1, type: any

La función head nos devuelve el primer elemento de la lista, y en caso de estar vacía nos lanza un Error aunque también podríamos retornar undefined, eso ya depende de ti. El problema de head es que su salida es de tipo any.

Vamos a intentar arreglar esta situación con TS

function head<T extends any[]>(array: T): Head<T>;

const my_array: [number, string, object] = [1, "hello", {}];
head(my_array);
// out: 1, type: number

Ahora nuestra función es mas segura, head recibe un parámetro T restringida en las listas y ademas retorna el primer elemento conservando su tipo (Head<T>).

Nota: definimos my_array especificando el tipo de manera explicita, sino lo hacemos así TS deduce my_array como una unión de los tipos (number | string | object)[] y no es lo que queremos.

Type HEAD

Veamos que es Head:

type Head<T extends any[]> = T extends [] ? never : T[0];

Head toma una lista luego comprobamos si T es una lista vacía y devolvemos never, en caso contrario devolvemos el primer elemento de T. Recuerda que never designa un valor que nunca ocurre y nos viene perfecto para efectos secundarios como lanzar excepciones. También tiene otros usos que veremos después.

Al final quedaría así.

type Head<T extends any[]> = T extends [] ? never : T[0];

function head<T extends any[]>(array: T): Head<T> {
  if (array.length === 0) throw new Error("array is empty");
  return array[0];
}

head(my_array);
// out: 1, type: number

head([] as []);
// throw Error, type: never

type Number = Head<typeof my_array>
// type: number 

Discussion (0)