Functional programming with fp-ts and Typescript
Recently, I have started using a library called fp-ts in my Node/Typescript projects. This tool enables you to write functional code with types like Either, Option, Monad and all that confusing stuff.
In this post, I will show you how I wrote an authentication HTTP endpoint using Typescript, Express and, of course, fp-ts.
We are going to write an endpoint that receives a JSON with user credentials and returns a JWT token or 401 UNAUTHORIZED
response:
POST /signin
{ "email": "bartolo@mail.com", "password": "1234" } }
First, let's write some boilerplate Express code:
import express from "express"
const app = express()
app.use(bodyParser.json()) //enables json body deserializer
app.post("/signin", handleSignIn)
app.listen(8080)
Even if you have never used Express library before, I think this code is self-explanatory. Let's see how handleSignIn
function looks like.
import { fold } from "fp-ts/lib/Either"
function handleSignIn(req: Request, res: Response) {
const { email, password } = req.body
fold(replyUnauthorized(res), replyToken(res))(signIn(email, password))
}
In the first line, we basically extract email and password from request body. Nothing special. The second expression is the interesting one. It can be read as "If signIn returns an error, reply with unauthorized response, otherwise, reply with a token". Here are replyUnauthorized
and replyToken
functions:
function replyUnauthorized(res: Response): (error: Error) => void {
return error => res.status(401).end()
}
function replyToken(res: Response): (token: string) => void {
return token => res.json({ token })
}
In order to understand how fold
function works, we need to introduce Either
type first. Let's deep into signIn function:
import { right, left, Either } from "fp-ts/lib/Either"
function signIn(email: string, password: string): Either<Error, string> {
const isValid: boolean = authenticate(email, password)
return isValid
? right(generateToken(email))
: left(new Error("bad credentials"))
}
As you see, this function returns Either<Error, string>
; it means an Error
or a String
(the token). Error
return type is the left side result, String
is the right
result. So, we can return left
or right
with its respective value, using the two functions fp-ts provides for that. With that in mind signIn
function code is quite intuitive: it returns a token when credentials are right, or an error otherwise. Comming back to handleSignIn
function, we can now understand better what is going on. This is the fold
function signature:
function fold<E, A, B>(onLeft: (e: E) => B, onRight: (a: A) => B): (ma: Either<E, A>) => B { ... }
It receives two functions as parameters:
onLeft
: In our example, replyUnauthorized, that will be executed when Either left result is returned;Error
, in this case.onRight
: In our example,replyToken
, that will be executed when Either right result is returned;string
, in this case.
And returns another function that receives the Either
value to be evaluated; in our case, the result of signIn function.
We have seen the usage of Either
type and fold
function, but fp-ts is a very powerful library with many other types and operators. If you are considering to start writing functional code in Typescript, you definitely should check it.