Skip to main content

Mónada Either en TypeScript

⏱ Dedicación recomendada: 0 minutos
Esto considera el contenido visible y relevante, e ignora texto colapsado o marcado como opcional.


En TypeScript, aunque no existe un tipo Either nativo como en Haskell, podemos modelar un comportamiento similar utilizando Unión de Tipos y objetos discriminados. TypeScript permite definir tipos que pueden ser uno de varios valores, lo que nos permite imitar la semántica de Either.

Implementación de Either en TypeScript

Podemos crear una implementación de Either en TypeScript utilizando una unión de tipos para representar Left y Right.

type Either<L, R> =
| { type: 'Left'; value: L }
| { type: 'Right'; value: R };

Mónada Either

Para que Either sea una mónada, necesitamos implementar las funciones flatMap y unit:

const unit = <L, R>(value: R): Either<L, R> => right(value);

class Left<L> {
readonly type = 'Left';
constructor(public value: L) {}

flatMap<T>(_fn: (value: R) => Either<L, T>): Either<L, T> {
return this as Either<L, T>;
}
}

class Right<R> {
readonly type = 'Right';
constructor(public value: R) {}

flatMap<T>(fn: (value: R) => Either<L, T>): Either<L, T> {
return fn(this.value);
}
}

Ejemplo de Validación de Contraseña

Supongamos que queremos validar una contraseña en TypeScript utilizando Either:

const validateLength = (password: string): Either<string, string> =>
password.length >= 8
? unit(password)
: new Left("Password is too short");

const validateContainsNumber = (password: string): Either<string, string> =>
/\d/.test(password)
? unit(password)
: new Left("Password must contain a number");

const validatePassword = (password: string): Either<string, string> =>
unit(password)
.flatMap(validateLength)
.flatMap(validateContainsNumber);

Comparación Final

CaracterísticaKotlinTypeScript
ImplementaciónUsa clases selladas para modelar Either, con una distinción clara entre Left y Right.Se modela utilizando unión de tipos y objetos discriminados, aprovechando las capacidades de TypeScript.
ExhaustividadEl compilador garantiza que todos los casos de Either sean manejados, proporcionando seguridad de tipos.En TypeScript, el uso de type guards ayuda a manejar todos los casos, pero no es tan estricto como Kotlin.
Compatibilidad con FlatMapKotlin permite fácilmente extender Either con métodos como flatMap directamente en la clase sellada.En TypeScript, se necesita definir flatMap en las clases Left y Right manualmente para lograr el mismo comportamiento.
Uso de funciones de extensiónKotlin permite definir funciones de extensión directamente sobre Either para mejorar su funcionalidad.TypeScript no soporta funciones de extensión directamente, pero se puede simular usando prototipos.
Seguridad en tiempo de compilaciónKotlin ofrece seguridad en tiempo de compilación con verificación exhaustiva de tipos y casos.TypeScript proporciona cierta seguridad en tiempo de compilación, pero es menos estricta que en Kotlin debido a su naturaleza de tipado estructural.

Ventajas y Desventajas de Either en TypeScript

Beneficios

  • Flexibilidad de Tipado: La implementación de Either en TypeScript permite aprovechar la flexibilidad del sistema de tipos y de los type guards, lo que proporciona versatilidad en el manejo de valores.
  • Compatibilidad con el Ecosistema: TypeScript, al estar integrado con JavaScript, permite que Either se combine fácilmente con otras herramientas y bibliotecas del ecosistema, lo que facilita su uso en aplicaciones web.
  • Uso de Objetos Discriminados: Los objetos discriminados de TypeScript facilitan la verificación de tipos en tiempo de ejecución y la implementación de patrones similares a los de lenguajes funcionales.

Limitaciones

  • Menos Seguridad que Kotlin: Aunque TypeScript proporciona verificación en tiempo de compilación, no es tan estricto como Kotlin, lo que puede resultar en errores no detectados si no se manejan todos los casos explícitamente.
  • Sintaxis Verbosa: La implementación de Either en TypeScript puede ser más detallada y menos intuitiva que en Kotlin, especialmente cuando se extienden las funcionalidades con métodos como flatMap.
  • Limitaciones de Extensión: TypeScript no soporta funciones de extensión de manera nativa, lo que obliga a utilizar prototipos o clases, lo que puede ser menos intuitivo y menos seguro en términos de tipado.

¿Qué Aprendimos?

En esta lección, hemos explorado cómo implementar y utilizar la mónada Either en TypeScript, comparando sus características y funcionalidades con la implementación en Kotlin. Aquí están los puntos clave que hemos aprendido:

  1. Modelado de Tipos Algebraicos: Tanto en Kotlin como en TypeScript, el tipo Either permite modelar operaciones que pueden resultar en un éxito (Right) o en un fallo (Left). Mientras que Kotlin ofrece una implementación nativa más estructurada utilizando clases selladas, TypeScript utiliza unión de tipos y objetos discriminados para lograr un comportamiento similar.
  2. Extensibilidad y Composición:
    • En Kotlin, se puede extender Either de forma intuitiva mediante métodos y funciones de extensión, lo que facilita su uso y composición.
    • En TypeScript, aunque se pueden simular estas extensiones utilizando prototipos o definiendo métodos en clases, el enfoque es menos directo y puede ser más complejo.
  3. Seguridad en Tiempo de Compilación:
    • Kotlin proporciona un control exhaustivo en tiempo de compilación, asegurando que todos los casos sean manejados y que los tipos sean verificados con precisión, reduciendo el riesgo de errores en tiempo de ejecución.
    • TypeScript ofrece cierta verificación en tiempo de compilación, pero debido a su naturaleza de tipado dinámico y estructural, no alcanza el mismo nivel de exhaustividad que Kotlin. Esto significa que, si bien se pueden manejar errores de forma segura, hay más posibilidades de que se ignoren casos o se produzcan errores no detectados.
  4. Patrones Funcionales en TypeScript:
    • A pesar de las diferencias, TypeScript sigue permitiendo el uso de patrones funcionales como el encadenamiento de operaciones usando flatMap, lo que resulta útil para componer funciones que manejan errores de forma explícita.
    • La flexibilidad del sistema de tipos de TypeScript, combinada con type guards, facilita la creación de estructuras funcionales que son fáciles de integrar en el ecosistema JavaScript.

Reflexión Final

La implementación de Either en TypeScript muestra cómo un lenguaje orientado a objetos y tipado estructural puede adoptar conceptos de lenguajes funcionales para manejar errores de forma más explícita y segura. Aunque hay limitaciones en comparación con Kotlin, TypeScript sigue siendo una opción potente para desarrollar aplicaciones que se benefician de enfoques funcionales, especialmente en el contexto de desarrollo web.

Con este conocimiento, ahora puedes aplicar Either en proyectos TypeScript para manejar errores de forma clara, reduciendo el uso de excepciones y promoviendo un enfoque más seguro y funcional en tu código.