Pick from validators
I'm working on a common library for a number of micro services that consume roughly the same environment variables. I'd like to provide definitions for all possible variables in my module, then allow each application to select the definitions they are interested in and ignore the rest.
I was thinking I could do this by wrapping the invocation of envalid.cleanEnv in my own function and pass a list of vars the application was interested in, something like this (the following code does not work FYI):
import { cleanEnv } from 'envalid';
enum Var {
BindAddr = 'BIND_ADDR',
BindPort = 'BIND_PORT',
JwkFile = 'JWK_FILE'
// ... many more
}
function pick<T, U extends keyof T>(obj: T, keys: U[]): Pick<T, U> {
const picked = {} as Record<U, any>;
for (const key of keys) {
picked[key] = obj[key];
}
return picked as Pick<T, U>;
}
export function get<T extends Var>(varsToSelect: T[]) {
const validators = {
[Var.BindAddr]: str({ default: 'localhost' }),
[Var.BindPort]: num({ default: 8000 }),
[Var.JwkFile]: str()
};
return cleanEnv(
getEnv(),
pick<typeof validators, T>(validators, vars)
)
}
I can't figure out how to get the resulting object typed correctly, though. This is what I'm after:
// would be awesome to get this from the argument alone, instead of effectively duplicating the list in the generic argument
const config = get<Var.BindAddr | Var.BindPort>([
Var.BindAddr,
Var.BindPort
]);
config.BIND_ADDR //=> should be present of type string
config.BIND_PORT //=> should be present of type number
config.JWK_FILE //=> should be absent
Does this make sense? Is this possible? How can I accomplish this?
Have you tried the latest envalid, 8.0.0-alpha.2? Seems to be typed as desired for me when I run your example with it:
No, I was trying the latest stable release. I'll give 8.0.0-alpha.2 a try and let you know what I see.