How to read config values from env using io-ts

Even in simple, smaller applications we have to deal with configuration of some kind. Since we all know that hardcoding config values sucks, we tend to pick the easy-yet-flexible and powerful method - reading values from environmental variables. In this short post, I’ll show you how to embrace functional concepts and make configuration reading type safe. And, as a bonus, you’ll get fancy error reporting in case something goes left.

Our goal is to read all necessary values at app startup — we absolutely don’t want to find out that the database password is missing in the middle of http request processing — and terminate with a human-readable message in the console if something is missing or invalid.

We will use the excellent fp-ts & io-ts libraries from Giulio Canti. Some could argue that there are other fish in the sea, but if you aim for the best, search no more ;-)

Enough talk, let’s start with the code!

-- CODE language-js --

As you can see, decoding yields transform either the value or error if something fails.

Guilio provides us with a few built-in decoders and combinators, so we can create our reader by combining them (as any decent functional developer would do).

-- CODE language-js --

Primitive decoders don’t do anything fancy:

-- CODE language-js --

But as soon as we combine them, the magic starts to happen:

-- CODE language-js --

Let’s say, we need to read db user, password, and port that our application will be listening on. We use type combinator for composing the decoder:

-- CODE language-js --

Maybe we want some of the properties to be optional and to supply default values:

-- CODE language-js --

Now we can extract static type from the decoder instance:

-- CODE language-js --

And use it in our application like this:

-- CODE language-js --

Happy functional coding! λ

Honza Trtík
Doing stuff. Occasional functional inquisition.