# Typed Configuration

https://github.com/FlashSystems/just-config#no-data-types makes an interesting argument that configuration shouldn’t be typed. I disagree with the conclusion but agree with the premise. Me likey types, and I think you can get the best of both worlds.

To explain further: The example used is cache_timeout=X. Should the value of X be constrained? If you’re validating a configuration file, you would constrain X to be a certain type. If you’re parsing a configuration file, you would not necessarily constrain X.

So, Parse, don’t validate strikes again.

Going back to the example, we have a situation here of mismatched concerns.

1. APIs should be Forwards and Backwards Compatible.
2. Configuration is also an API
3. Typing by validation is inherently not forwards/backwards compatible.

In the example, X is originally of type Number, then Number | Disabled, then Number | Disabled (but with support for parsing Infinity as a number).

So, the proper type of a configuration value is really {key: string, value: bytestring}. This can be later parsed into a refined type when needed rather than validated at consumption.

Importantly… Parsing here does not prevent you from keeping the unparsed configuration around.

let cfg = getCfg() // Record<string, bytestring>

let cache_timeout = parseCacheTimeout(cfg)

fn parseCacheTimeout(cfg) {
let timeout =
// version 1
try parseNum(cfg.?cache_timeout)
or
// version 2
try parseString(cfg?.cache_timeout, "disabled")
or
// version 3
try parseInfinity(cfg?.cache_timeout)
// ... version N
// forwards compat
or
configDefaultWithWarning(cfg, "cache_timeout")

return timeout
}