Typing import.meta.env
For most use cases, you'll want to access your environment variables in your client code. In a Vite project, this is done via import.meta.env.
With ArkEnv, this can be typesafe with the one-time setup below. After this, each time you add/remove environment variables from your schema, your import.meta.env will always be typesafe - no codegen needed.
Link to section: setupSetup
Important
You must have the core arkenv package installed as a dependency in your project. See ArkEnv quickstart for instructions.
Add this to a vite-env.d.ts file in your src directory:
/// <reference types="vite/client" />
type ImportMetaEnvAugmented =
import("@arkenv/vite-plugin").ImportMetaEnvAugmented<
typeof import("../vite.config").Env
>;
interface ViteTypeOptions {
// By adding this line, you can make the type of ImportMetaEnv strict
// to disallow unknown keys.
// See: https://vite.dev/guide/env-and-mode#intellisense-for-typescript
// ⚠️ This option requires Vite 6.3.x or higher
strictImportMetaEnv: unknown;
}
// Augment import.meta.env with your schema
// Only `VITE_*` prefixed variables will be included
interface ImportMetaEnv extends ImportMetaEnvAugmented {}Link to section: usageUsage
Once set up, import.meta.env is fully typesafe:
// TypeScript knows about your VITE_* variables
const apiUrl = import.meta.env.VITE_API_URL; // ✅ Typesafe
const port = import.meta.env.PORT; // ❌ Error: PORT is not in ImportMetaEnv
// Autocomplete works too!
import.meta.env.VITE_ // Shows all your VITE_* variablesLink to section: how-it-worksHow it works
The ImportMetaEnvAugmented type:
- Extracts the inferred type from your schema (the result of
type()from arkenv) - Filters to only include variables matching the Vite prefix (defaults to
"VITE_") - Makes them available on
import.meta.envwith full type safety
Server-only variables (like PORT) are automatically excluded from the client bundle and won't appear in import.meta.env.
Read more in the Vite documentation.
Link to section: as-your-project-growsAs your project grows
You might want to define your schema in a dedicated file for better organization:
import { type } from "arkenv";
export const Env = type({
PORT: "number.port",
VITE_API_URL: "string",
VITE_API_KEY: "string",
VITE_MY_NUMBER: "number",
VITE_MY_BOOLEAN: "boolean",
});
export type Env = typeof Env.infer;import arkenvVitePlugin from "@arkenv/vite-plugin";
import { defineConfig } from "vite";
import { Env } from "./src/env";
export default defineConfig({
plugins: [arkenvVitePlugin(Env)],
});/// <reference types="vite/client" />
type ImportMetaEnvAugmented =
import("@arkenv/vite-plugin").ImportMetaEnvAugmented<
typeof import("./env").Env
>;
interface ViteTypeOptions {
strictImportMetaEnv: unknown;
}
interface ImportMetaEnv extends ImportMetaEnvAugmented {}Important
Imports will break type augmentation
If the ImportMetaEnv augmentation does not work, make sure you do not have any import statements in vite-env.d.ts. See the TypeScript documentation for more information.
Link to section: creditCredit
This implementation is inspired by vite-plugin-validate-env by Julien-R44.