Type Casting
Smart type conversion with the SecretValue wrapper.
Environment variables are always strings, but your application often needs other types. The SecretValue wrapper provides type-safe conversion methods.
The SecretValue Wrapper#
When you call secrets.get(key), you get a SecretValue object:
const secrets = await redenv.load();
const portValue = secrets.get("PORT");
// portValue is a SecretValue, not a stringThis wrapper provides transformation methods while preserving the ability to use the value directly.
Conversion Methods#
toInt()#
Parse the value as an integer:
const port = secrets.get("PORT").toInt();
// "3000" → 3000
const timeout = secrets.get("TIMEOUT", 5000).toInt();
// undefined → 5000 (default)Returns undefined if the value can't be parsed and no default was provided.
toBool()#
Parse the value as a boolean:
const debug = secrets.get("DEBUG").toBool();
// "true" → true
// "false" → false
const enabled = secrets.get("FEATURE_FLAG", false).toBool();
// undefined → false (default)Truthy values: "true", "1", "yes", "on", "t"
Falsy values: "false", "0", "no", "off", "f"
toJSON()#
Parse the value as JSON:
const config = secrets.get("APP_CONFIG").toJSON();
// '{"timeout": 5000}' → { timeout: 5000 }
const defaults = secrets.get("MISSING", { fallback: true }).toJSON();
// undefined → { fallback: true }Returns the parsed object, or undefined if parsing fails and no default was provided.
toString()#
Get the string value (or default):
const env = secrets.get("NODE_ENV", "development").toString();
// undefined → "development"Default Values#
All methods accept a default value via the get() call:
// With defaults
const port = secrets.get("PORT", 3000).toInt(); // 3000 if missing
const debug = secrets.get("DEBUG", false).toBool(); // false if missing
const log = secrets.get("LOG_LEVEL", "info").toString(); // "info" if missingType-aware defaults:
// If the secret is missing, default values maintain their type
const count = secrets.get("COUNT", 10).toInt();
// Returns 10 (number), not "10" (string)
const enabled = secrets.get("ENABLED", true).toBool();
// Returns true (boolean), not "true" (string)Automatic Coercion#
The SecretValue implements Symbol.toPrimitive, allowing automatic type coercion:
const port = secrets.get("PORT", 3000);
// In string context
console.log(`Server running on port ${port}`);
// Output: Server running on port 3000
// In numeric context
const nextPort = +port + 1;
// Works correctly: 3001Console Logging#
SecretValue also implements custom inspection, so logging works intuitively:
const apiKey = secrets.get("API_KEY");
console.log(apiKey);
// Output: sk_live_abc123 (the actual value)Practical Examples#
Server Configuration#
const secrets = await redenv.load();
const config = {
port: secrets.get("PORT", 3000).toInt(),
host: secrets.get("HOST", "0.0.0.0").toString(),
ssl: secrets.get("SSL_ENABLED", false).toBool(),
workers: secrets.get("WORKERS", 4).toInt(),
};
app.listen(config.port, config.host);Feature Flags#
const secrets = await redenv.load();
const features = {
betaMode: secrets.get("BETA_MODE").toBool(),
maxUsers: secrets.get("MAX_USERS", 1000).toInt(),
allowedDomains: secrets.get("ALLOWED_DOMAINS", "[]").toJSON() as string[],
};
if (features.betaMode) {
enableBetaFeatures();
}Complex JSON Configurations#
const secrets = await redenv.load();
interface DatabaseConfig {
host: string;
port: number;
ssl: boolean;
}
const dbConfig = secrets
.get("DATABASE_CONFIG", {
host: "localhost",
port: 5432,
ssl: false,
})
.toJSON() as DatabaseConfig;Type Safety#
For TypeScript, you can add type assertions:
const secrets = await redenv.load();
// Type assertion
const config = secrets.get("CONFIG").toJSON() as AppConfig;
// Or with generics (if your config is predictable)
interface AppConfig {
apiUrl: string;
timeout: number;
}
// Note: toJSON's generic parameter
const config = secrets.get("CONFIG").toJSON<AppConfig>();