CtroEnv
ctroenvType-Safe Environment Variables
Getting StartedQuick StartCore Concepts
defineEnv()string()number()boolean()pick()Chainable MethodsRefinementsError HandlingSchema Composition
CLI Overviewctroenv validatectroenv generatectroenv checkctroenv docsctroenv initCLI Configuration
Node AdapterVite AdapterNext.js Adapter
Migration from t3-envMigration from envalidMigration from dotenv

Refinements

Apply standalone refinement functions like url(), email(), min(), max(), and more.

  1. Docs
  2. Core API

Refinements

Refinements are standalone functions that wrap an existing validator to add a constraint. They are the building blocks used internally by validator methods like .url() and .min().

Independent Refinements

These functions are exported from @ctroenv/core for cases where you want to apply a refinement to a custom validator.

url

function url(): <T extends string>(v: Validator<T>) => Validator<T>

Wraps a string validator to require a valid URL:

import { url, string } from "@ctroenv/core"

const myUrlValidator = url()(string().min(1))

email

function email(): <T extends string>(v: Validator<T>) => Validator<T>

Wraps a string validator to require a valid email format.

regex

function regex(pattern: RegExp, message?: string): <T extends string>(v: Validator<T>) => Validator<T>

Wraps a string validator to require a regex match.

min

function min<N extends number>(limit: N): {
  <T extends string>(v: Validator<T>): Validator<T>
  <T extends number>(v: Validator<T>): Validator<T>
}

Wraps a string or number validator to require a minimum length/value.

  • For strings: checks value.length >= limit
  • For numbers: checks value >= limit

max

function max<N extends number>(limit: N): {
  <T extends string>(v: Validator<T>): Validator<T>
  <T extends number>(v: Validator<T>): Validator<T>
}

Wraps a string or number validator to require a maximum length/value.

  • For strings: checks value.length <= limit
  • For numbers: checks value <= limit

port

function port(): <T extends number | string>(v: Validator<T>) => Validator<T>

Wraps a number or string validator to require a valid port (1-65535).

integer

function integer<T extends number>(): (v: Validator<T>) => Validator<T>

Wraps a number validator to require an integer value.

When to Use Refinements vs Methods

In most cases, you should use the type-specific methods:

string().url()       // ✅ Preferred
number().int()       // ✅ Preferred

Standalone refinements are useful when building custom validator factories or when you need to apply a refinement that isn't available as a method:

import { url, createValidator, applyChain } from "@ctroenv/core"

const myUrlValidator = applyChain(
  createValidator<string>(
    (input, context) => { /* custom parsing */ },
    { typeLabel: "url" },
  ),
)

// Apply the URL refinement
const validated = url()(myUrlValidator)

How is this guide?

Edit on GitHub

Last updated on Jun 24, 2026

PreviousChainable MethodsNextError Handling

On this page

Independent RefinementsurlemailregexminmaxportintegerWhen to Use Refinements vs Methods