Most TypeScript projects treat environment variables like second-class citizens. They're string | undefined everywhere, asserted with ! and parsed with parseInt(). TypeScript can't help because process.env is typed as Record<string, string | undefined>.
Schema-based validation fixes this. But most solutions bring zod, which adds 50 KB to your bundle. CtroEnv does it with zero dependencies and 6.5 KB gzipped.
How Inference Works
The type system reads each validator's configuration at compile time:
type InferredValue<V> =






