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 ;-)
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).
Primitive decoders don’t do anything fancy. But as soon as we combine them, the magic starts to happen. 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.
Maybe we want some of the properties to be optional and to supply default values. Now we can extract static type from the decoder instance and use it in our application.
Happy functional coding! λ