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.
Feature | type | arkenv (default) |
---|---|---|
Primary Use Case | Schema definition separate from validation | Environment variable handling with immediate validation |
Input | Any object (usually environment variables) | process.env or custom object |
Output | Validated object | Parsed environment variables |
When to Use | When you want to define schema in one file and validate in another | Environment variables (most common) |
Recommended for | Advanced users, modular architecture | Most 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.