Monadic types for Typescript
npm install monads-typescriptIn functional programming, a monad) is a design pattern that allows structuring programs generically while automating away boilerplate code needed by the program logic.
In a strongly typed liked language like Scala, with built-in types like the Option type, you are very likely
to have already used or will eventually end up using monads without even knowing you are using them. This project
is my attempt at understanding monads by writing them, and I decided to use TypeScript because it forces me to
build monads from "scratch", but with support for strong typing.
```
npm i monads-typescript
Import the appropriate static methods from the library like so:
`ts`
import { left, right } from 'monads-typescript';
import { maybe } from 'monads-typescript';
...
monad, is based on Scala's
Option type. It's very useful when you want
to encapsulate computation on values that might be null or undefined.Here's an example of some code you might find yourself writing in JavaScript/TypeScript:
`ts
const greetUser = (userId) => {
const user = getUser(userId);
let name;
if (user) {
name = user.getName();
}
if (name) {
return Hello ${name};
} else {
return 'Hello, guest';
}
}
` Using the
Maybe monad:`ts
const greetUser = (userId: number) => {
return maybe(getUser(userId))
.map((user) => user.getName())
.map((name) => Hello, ${name})
.getOrElse('Hello, guest');
};
`Depending on your application, you could simplify this even further, like so:
`ts
const getName = (user: User) => user.getName();
const greetName = (name: string) => Hello, ${name};const greetUser = (userId: number) => {
return maybe(getUser(userId))
.map(getName)
.map(greetName)
.getOrElse(greetName('guest'));
};
` As you can see, using the
Maybe monad abstracts away a lot of boilerplate, giving you a flat, composable
interface to work with that's much more readable.$3
Similarly, the Either monad is based on Scala's
Either type.The
Either monad is useful when you want to represent one of two possible types. An instance of
Either is either a Left or Right. By convention, Right is used to represent a success type, while
Left is used to hold a failure type.Here's another example of some code you might write in imperative TypeScript:
`ts
const getAge = (uid: number): number | never => ...;
const canDrink = (age: number): boolean => age >= 18;const okToDrink = (uid: number) => {
try {
const age = getAge(uid);
if (age) {
return canDrink(age);
}
} catch {
return false;
}
}
`Rewriting this using the
Either monad:`ts
const getAge = (uid: number): Either => ...; // the left represents an error string
const canDrink = (age: number): boolean => age >= 18;const okToDrink = (uid: number) => {
getAge(uid).fold(
(error) => {
console.log(
Error getting age: ${error});
return false;
},
(age) => canDrink(age)
)
}
``