---
title: Field Types
description: Reference for all ten env builder functions and their chain methods in @envlock/core.
url: https://pr-1-b9e16090e83d.thally.app/envlock/field-types
---

# Field Types

Reference for all ten env builder functions and their chain methods in @envlock/core.

Every environment variable in an Envlock schema is declared with one of ten
builder functions on the `env` namespace. Each builder returns a required,
non-secret field by default. Chain methods refine a field into optional,
defaulted, secret, or documented variants.

All builders and chain methods are imported from `@envlock/core`:

```ts
import { env } from "@envlock/core";
```

## Builder functions

### `env.string()`

Any string value passed through verbatim. No trimming or transformation is
applied.

```ts
SESSION_SECRET: env.string()
```

### `env.number()`

A finite number. Leading and trailing whitespace is trimmed before parsing.
Blank strings, `NaN`, and `Infinity` are rejected.

```ts
RATE_LIMIT: env.number()
```

### `env.integer()`

A safe integer only (within the range of `Number.isSafeInteger`). Non-integer
numbers and values outside the safe integer range are rejected.

```ts
MAX_RETRIES: env.integer()
```

### `env.boolean()`

Accepts `true`/`false`, `1`/`0`, `yes`/`no`, and `on`/`off`.
Matching is case-insensitive.

```ts
DEBUG: env.boolean()
```

### `env.port()`

An integer in the range 1 through 65535.

```ts
PORT: env.port()
```

### `env.url(options?)`

An absolute URL validated with `new URL()`. You can optionally pass a
`protocols` array to restrict which protocols are accepted. Each protocol
string must include the trailing colon (for example `"https:"`, not `"https"`).

```ts
API_ENDPOINT: env.url()
DATABASE_URL: env.url({ protocols: ["postgres:", "postgresql:"] })
```

### `env.enum(values)`

Exactly one of the literal string members passed as an array. The array must
contain at least one value.

```ts
LOG_LEVEL: env.enum(["debug", "info", "warn", "error"])
NODE_ENV: env.enum(["development", "production", "test"])
```

### `env.json()`

Parses the value with `JSON.parse`. Syntax errors become `invalid` issues.
You can supply a type parameter to narrow the parsed type.

```ts
FEATURE_FLAGS: env.json<Record<string, boolean>>()
```

### `env.duration()`

Converts a human-readable duration string to milliseconds. Recognised suffixes
are `ms` (milliseconds), `s` (seconds), `m` (minutes), `h` (hours), and
`d` (days). A bare number without a suffix is also accepted.

| Input   | Result (ms) |
|---------|-------------|
| `250ms` | 250         |
| `30s`   | 30000       |
| `5m`    | 300000      |
| `2h`    | 7200000     |
| `1d`    | 86400000    |

```ts
REQUEST_TIMEOUT: env.duration()
```

### `env.list(options?)`

Splits the value by a separator (default: comma), trims each item, and drops
empty items. Pass a custom `separator` string in the options if your list uses a
different delimiter.

```ts
ALLOWED_ORIGINS: env.list()
TAGS: env.list({ separator: ";" })
```

## Chain methods

Every chain method returns a **new** field instance. The original is never
mutated -- fields are immutable (frozen). You can chain multiple methods in any
order:

```ts
PORT: env.port().default(3000).describe("HTTP listen port")
```

### `.optional()`

Marks the field as optional. When the variable is absent or empty, no issue is
reported and the property is omitted from the result object. In the inferred
type, optional fields become optional properties.

```ts
DEBUG: env.boolean().optional()
// Inferred as DEBUG?: boolean
```

### `.default(value)`

Provides a default value used when the variable is absent or empty. A field
with a default is treated as required in the inferred type (it always has a
value). Setting a default clears the optional flag.

```ts
PORT: env.port().default(3000)
// PORT is always present in the result
```

### `.secret()`

Marks the field as containing sensitive data. Secret values are masked with
`"••••••"` in validation issues, `.env.example` output, schema descriptions,
and `redact()` results. The field keeps its required or optional status.

```ts
DATABASE_URL: env.url({ protocols: ["postgres:"] }).secret()
```

### `.describe(text)`

Attaches a human-readable description. The text appears in `.env.example`
output (as a comment above the variable) and in `describeSchema()` results.

```ts
PORT: env.port().default(3000).describe("HTTP listen port")
```

### `.example(text)`

Sets a sample raw value shown in `.env.example` output. For secret fields, the
example value is never rendered -- the assignment line is always left empty.

```ts
DATABASE_URL: env
  .url({ protocols: ["postgres:"] })
  .secret()
  .describe("Primary Postgres connection string")
  .example("postgres://user:pass@localhost:5432/app")
```

## Comprehensive example

The following schema demonstrates multiple field types and chain methods
together:

```ts
import { defineEnv, env } from "@envlock/core";

export default defineEnv({
  NODE_ENV: env
    .enum(["development", "production"])
    .default("development")
    .describe("Runtime mode"),

  PORT: env
    .port()
    .default(3000)
    .describe("HTTP listen port"),

  DATABASE_URL: env
    .url({ protocols: ["postgres:", "postgresql:"] })
    .secret()
    .describe("Primary Postgres connection string")
    .example("postgres://user:pass@localhost:5432/app"),

  SESSION_SECRET: env
    .string()
    .secret()
    .describe("Key used to sign session cookies"),

  REQUEST_TIMEOUT: env
    .duration()
    .default(30_000)
    .describe("Upstream request timeout"),

  ALLOWED_ORIGINS: env
    .list()
    .default(["http://localhost:3000"])
    .describe("CORS allow-list"),

  FEATURE_FLAGS: env
    .json()
    .optional()
    .describe("Optional JSON object of feature toggles"),

  MAX_CONNECTIONS: env
    .integer()
    .default(10)
    .describe("Maximum database connection pool size"),

  VERBOSE_LOGGING: env
    .boolean()
    .optional()
    .describe("Enable verbose request logging"),

  LOG_LEVEL: env
    .enum(["debug", "info", "warn", "error"])
    .default("info")
    .describe("Application log level"),
});
```