envParsers
Turn environment strings into booleans, numbers, lists, JSON, URLs, and enums, with error messages that name the variable.
Import
import { envParsers } from 'next-dynenv'At a glance
| Parser | Returns | Not set | Invalid |
|---|---|---|---|
boolean(key, default = false) | boolean | default | default |
number(key, default = 0) | number | default | Throws |
array(key, default = []) | string[] | default | Never invalid |
json<T>(key, default?) | T | default, or throws | Throws |
url(key, default?) | string | default, or throws | Throws |
enum<T>(key, allowed, default?) | T | default, or throws | Throws |
"Not set" means undefined. Empty strings differ per parser: boolean and number treat blank values as not set, array returns [], and json, url, and enum throw.
Parsers read through env()
Every parser calls env(), so the same rules apply. In client components, use NEXT_PUBLIC_ keys and render PublicEnvScript or EnvScript. With the context approach, parse the strings from useEnvContext() yourself.
boolean()
envParsers.boolean(key: string, defaultValue?: boolean): booleanTrims and lowercases the value, then checks it against the truthy list.
| Value | Result |
|---|---|
true, 1, yes, on (any case) | true |
Any other value, including '' | false |
| Not set | defaultValue (false unless passed) |
Never throws. The default only applies when the variable is missing, so FLAG= turns a default-on flag off.
const debug = envParsers.boolean('NEXT_PUBLIC_DEBUG')
// Opt-out flag: on unless the variable is set to something other than a truthy value
const analytics = envParsers.boolean('NEXT_PUBLIC_ANALYTICS', true)number()
envParsers.number(key: string, defaultValue?: number): numberConverts with Number() and rejects anything that is not finite.
| Value | Result |
|---|---|
3000, 42 | 3000, 42 |
3.14, -42, 1e3, 0x10 | 3.14, -42, 1000, 16 |
'' or whitespace only | defaultValue (0 unless passed) |
| Not set | defaultValue |
abc, 3000px, Infinity | Throws |
Environment variable 'NEXT_PUBLIC_PAGE_SIZE' is not a valid number: 'abc'.
Expected a numeric value like '3000' or '3.14'.const pageSize = envParsers.number('NEXT_PUBLIC_PAGE_SIZE', 20)
const timeoutMs = envParsers.number('NEXT_PUBLIC_TIMEOUT_MS', 5000)Range checks stay yours: number() accepts -1 and 2.5 for a page size.
array()
envParsers.array(key: string, defaultValue?: string[]): string[]Splits on commas, trims each item, and drops empty items. Never throws for its content.
| Value | Result |
|---|---|
auth,payments,search | ['auth', 'payments', 'search'] |
auth , payments , | ['auth', 'payments'] |
'' | [] |
| Not set | defaultValue ([] unless passed) |
const features = envParsers.array('NEXT_PUBLIC_FEATURES')
if (features.includes('payments')) {
// render checkout
}Items cannot contain commas. Use json() for anything richer.
json()
envParsers.json<T = unknown>(key: string, defaultValue?: T): TParses with JSON.parse. The generic is a cast, not a check, so validate the shape when it matters.
import { envParsers } from 'next-dynenv'
import { z } from 'zod'
const Flags = z.object({ checkout: z.boolean(), search: z.boolean() })
// NEXT_PUBLIC_FLAGS={"checkout":true,"search":false}
const flags = Flags.parse(envParsers.json('NEXT_PUBLIC_FLAGS', { checkout: false, search: false }))Throws when the value is not set and there is no default:
Required environment variable 'NEXT_PUBLIC_FLAGS' is not defined.
Expected a JSON string value.And when the value is not valid JSON (including ''):
Environment variable 'NEXT_PUBLIC_FLAGS' is not valid JSON: '{checkout:true}'.
Expected a valid JSON string like '{"key":"value"}'.url()
envParsers.url(key: string, defaultValue?: string): stringChecks the value with new URL() and returns the original string unchanged, so https://api.example.com stays without the trailing slash new URL() would add. Any absolute URL passes, including postgres:// and mailto: schemes. Relative paths such as /api throw. The default is returned as is, without validation.
const apiUrl = envParsers.url('NEXT_PUBLIC_API_URL')
const cdnUrl = envParsers.url('NEXT_PUBLIC_CDN_URL', 'https://cdn.example.com')Required environment variable 'NEXT_PUBLIC_API_URL' is not defined.
Expected a valid URL.Environment variable 'NEXT_PUBLIC_API_URL' is not a valid URL: 'api.example.com'.
Expected a valid URL like 'https://example.com'.enum()
envParsers.enum<T extends string>(key: string, allowedValues: readonly T[], defaultValue?: T): TReturns the value when it exactly matches one of allowedValues. Matching is case-sensitive, so Production fails against 'production'. TypeScript infers T from the list; the default is typed against it but not checked at runtime.
const stage = envParsers.enum('NEXT_PUBLIC_STAGE', ['development', 'staging', 'production'] as const, 'development')
// stage: 'development' | 'staging' | 'production'Required environment variable 'NEXT_PUBLIC_STAGE' is not defined.
Expected one of: 'development', 'staging', 'production'.Environment variable 'NEXT_PUBLIC_STAGE' has invalid value: 'prod'.
Expected one of: 'development', 'staging', 'production'.Putting it together
Read config inside a function so values come from the request-time environment, not from whenever the module first loaded.
// lib/public-config.ts
import { envParsers } from 'next-dynenv'
export function getPublicConfig() {
return {
apiUrl: envParsers.url('NEXT_PUBLIC_API_URL'),
debug: envParsers.boolean('NEXT_PUBLIC_DEBUG'),
features: envParsers.array('NEXT_PUBLIC_FEATURES'),
pageSize: envParsers.number('NEXT_PUBLIC_PAGE_SIZE', 20),
stage: envParsers.enum('NEXT_PUBLIC_STAGE', ['development', 'staging', 'production'] as const, 'development'),
}
}Catch errors with a narrowed type to report them your way:
try {
getPublicConfig()
} catch (error) {
if (error instanceof Error) {
console.error(`Config error: ${error.message}`)
}
throw error
}Related
env()for raw stringsrequireEnv()for required strings- Troubleshooting for values that parse differently than expected