πŸŽ‰ We are now featured onΒ arktype.io!
ArkEnv

Type Function

Learn about ArkEnv's advanced type function for runtime validation with built-in environment-specific types.

Note

For most use cases, you should use the default arkenv export (which uses createEnv under the hood). The type function is useful when you want to separate schema definition from validation.

Tip

New to ArkEnv? Start with the Quickstart guide to learn the basics with the default arkenv export. This guide is for when you need to separate schema definition from validation.

ArkEnv exposes a type function that extends ArkType's type system with environment-specific validations. This function is useful when you want to define your schema in one place and validate environment variables at a different time or location.

#Basic Usage

import { type } from "arkenv";

const env = type({
  NODE_ENV: "string",
  HOST: "string.host",
  PORT: "number.port",
});

// Validate and transform environment variables
const result = env.assert({
  NODE_ENV: "development",
  HOST: "localhost",
  PORT: "3000", // String input, number output
});

console.log(result);
// { NODE_ENV: "development", HOST: "localhost", PORT: 3000 }

#Separation of Schema Definition and Validation

The main benefit of the type function is that you can define your schema in one place and validate environment variables elsewhere:

// config/env-schema.ts
import { type } from "arkenv";

export const envSchema = type({
  NODE_ENV: "string",
  HOST: "string.host",
  PORT: "number.port",
  API_KEY: "string?",
});
// config/env.ts
import { envSchema } from "./env-schema";

// Validate environment variables using the schema
export const env = envSchema.assert(process.env);
// vite.config.ts
import { defineConfig } from "vite";
import arkenv from "@arkenv/vite-plugin";
import { envSchema } from "./config/env-schema";

export default defineConfig({
  plugins: [arkenv(envSchema)],
});

This approach allows you to:

  • Reuse the same schema across different parts of your application
  • Define schema once and validate in multiple places
  • Keep configuration modular and organized

#Built-in Environment Types

#string.host

Validates hostnames and IP addresses:

const env = type({
  API_HOST: "string.host",
  DB_HOST: "string.host",
});

// Valid inputs
env.assert({ API_HOST: "localhost" });
env.assert({ API_HOST: "127.0.0.1" });
env.assert({ API_HOST: "api.example.com" });

// Invalid inputs
env.assert({ API_HOST: "invalid-host" }); // ❌ Throws error

#number.port

Validates and converts port numbers:

const env = type({
  PORT: "number.port",
  API_PORT: "number.port",
});

// Valid inputs (strings from environment variables)
const result = env.assert({ PORT: "3000" });
console.log(result.PORT); // 3000 (number)

// Valid port range: 1-65535
env.assert({ PORT: "8080" }); // βœ… Valid
env.assert({ PORT: "65535" }); // βœ… Valid

// Invalid inputs
env.assert({ PORT: "0" }); // ❌ Too low
env.assert({ PORT: "65536" }); // ❌ Too high
env.assert({ PORT: "invalid" }); // ❌ Not a number

#Advanced Usage

#Optional Fields

const env = type({
  REQUIRED: "string",
  OPTIONAL: "string?",
  PORT: "number.port?",
});

// Works with all fields
env.assert({
  REQUIRED: "value",
  OPTIONAL: "optional",
  PORT: "3000",
});

// Works with only required fields
env.assert({
  REQUIRED: "value",
  // OPTIONAL and PORT are omitted
});

#Nested Objects

const env = type({
  DATABASE: {
    HOST: "string.host",
    PORT: "number.port",
    NAME: "string",
  },
  API: {
    HOST: "string.host",
    PORT: "number.port",
  },
});

const result = env.assert({
  DATABASE: {
    HOST: "localhost",
    PORT: "5432",
    NAME: "myapp",
  },
  API: {
    HOST: "api.example.com",
    PORT: "443",
  },
});

#Arrays

const env = type({
  ALLOWED_ORIGINS: "string[]",
  PORTS: "number[]",
});

const result = env.assert({
  ALLOWED_ORIGINS: ["localhost", "127.0.0.1"],
  PORTS: [3000, 8080, 9000],
});

#Error Handling

The type function provides detailed error messages for validation failures:

const env = type({
  HOST: "string.host",
  PORT: "number.port",
});

try {
  env.assert({
    HOST: "invalid-host",
    PORT: "99999",
  });
} catch (error) {
  console.error(error.message);
  // HOST must be a valid hostname or IP address (was "invalid-host")
  // PORT must be a valid port number (was "99999")
}

#When to Use type vs arkenv (default export)

Important

Most users should use the default arkenv export for environment variables. Only use type when you need to separate schema definition from validation.

Featuretypearkenv (default)
Primary Use CaseSchema definition separate from validationEnvironment variable handling with immediate validation
InputAny object (usually environment variables)process.env or custom object
OutputValidated objectParsed environment variables
When to UseWhen you want to define schema in one file and validate in anotherEnvironment variables (most common)
Recommended forAdvanced users, modular architectureMost users
// βœ… RECOMMENDED: Using arkenv for immediate validation
import arkenv from "arkenv";

const env = arkenv({
  HOST: "string.host",
  PORT: "number.port",
});

// βœ… ADVANCED: Using type to separate schema definition from validation
import { type } from "arkenv";

// Define schema in one file
const envSchema = type({
  HOST: "string.host",
  PORT: "number.port",
});

// Validate in another file or at a later time
const validated = envSchema.assert(process.env);

#Common Use Cases for type:

  • Modular Architecture: Define schema in a shared config file, validate in different modules
  • Delayed Validation: Define schema early but validate environment variables later in your application lifecycle
  • Schema Reuse: Use the same schema definition for different validation scenarios
  • Testing: Define schema once and use it for testing different environment configurations

#Integration with Vite

The type function works seamlessly with the Vite plugin:

// vite.config.ts
import { defineConfig } from "vite";
import arkenv from "@arkenv/vite-plugin";
import { type } from "arkenv";

const envSchema = type({
  VITE_API_URL: "string",
  VITE_HOST: "string.host",
  VITE_PORT: "number.port",
});

export default defineConfig({
  plugins: [arkenv(envSchema)],
});

This ensures your environment variables are validated at build time with the same type definitions you use for runtime validation.