Type Generation
vite-env writes a vite-env.d.ts file to your project root so your editor knows the exact shape of every environment variable — without any manual type augmentation.
When It Is Generated
The file is written during the buildStart Vite hook, which fires on every dev server start and every production build. You never need to remember to regenerate it during normal development.
What It Creates
Two ambient module declarations are written to vite-env.d.ts:
virtual:env/client— contains only the client-side keys (those underclientin your schema, i.e.VITE_-prefixed variables)virtual:env/server— contains all keys: every server variable plus every client variable
All fields are typed readonly and optional fields (those using .optional() or .default() in Zod) get the ? modifier.
Zod to TypeScript Type Mapping
| Zod schema | TypeScript type |
|---|---|
z.string() | string |
z.number() | number |
z.boolean() | boolean |
z.enum([...]) | Union literal, e.g. 'debug' | 'info' |
z.optional(...) | Unwrapped inner type + ? on the field |
z.default(...) | Unwrapped inner type + ? on the field |
z.pipe(...) | Output type of the pipe |
| Anything else | string (fallback) |
Example Output
Given a schema with both server and client variables, the generated file looks like:
// Auto-generated by @vite-env/core
// Do not edit manually — re-generated on every dev server start and build
declare module 'virtual:env/client' {
const env: {
readonly VITE_API_URL: string
readonly VITE_APP_NAME: string
readonly VITE_DEBUG?: boolean
readonly VITE_LOG_LEVEL?: 'debug' | 'info' | 'warn' | 'error'
}
export { env }
export default env
}
declare module 'virtual:env/server' {
const env: {
readonly DATABASE_URL: string
readonly JWT_SECRET: string
readonly DB_POOL_SIZE?: number
readonly REDIS_URL?: string
readonly VITE_API_URL: string
readonly VITE_APP_NAME: string
readonly VITE_DEBUG?: boolean
readonly VITE_LOG_LEVEL?: 'debug' | 'info' | 'warn' | 'error'
}
export { env }
export default env
}Setup Tips
Add to .gitignore
vite-env.d.ts is generated output, not source. Add it to your .gitignore:
vite-env.d.tsMake sure TypeScript sees it
Your tsconfig.json must include the project root (or the file explicitly) so the declarations are picked up:
{
"include": ["."]
}Or add the file explicitly:
{
"include": ["vite-env.d.ts", "src"]
}Postinstall pattern
On CI or fresh clones the file will not exist until the first build. Add a postinstall script so it is generated immediately after npm install:
{
"scripts": {
"postinstall": "vite-env types"
}
}Manual trigger
You can regenerate the file at any time without starting a build:
npx vite-env typesThis is useful when the file gets out of date after pulling changes to env.ts.