1. 为什么需要强化环境变量类型安全?
在Vite+TypeScript项目中,环境变量通过import.meta.env访问时默认只有基础类型推断。这意味着:
// 默认情况下只能获得string|boolean|undefined等基础类型 const apiUrl = import.meta.env.VITE_API_URL实际开发中我们会遇到几个典型问题:
- 缺少必填校验:生产环境必需的变量在开发阶段可能被遗漏
- 类型不精确:数字类型的端口号被识别为string
- 无智能提示:无法通过代码补全快速输入变量名
2. 类型定义方案设计
2.1 基础类型声明
在src/env.d.ts中扩展ImportMetaEnv接口:
interface ImportMetaEnv { readonly VITE_APP_TITLE: string readonly VITE_API_TIMEOUT: number readonly VITE_USE_MOCK?: boolean }2.2 必填校验实现
通过类型工具实现运行时校验:
type EnvKey = keyof ImportMetaEnv function checkRequiredVars(keys: EnvKey[]) { keys.forEach(k => { if (!import.meta.env[k]) { throw new Error(`Missing required env var: ${k}`) } }) } // 启动时校验 checkRequiredVars(['VITE_API_BASE_URL'])3. 高级类型技巧
3.1 枚举类型转换
处理预定义的枚举值:
type EnvMode = 'development' | 'test' | 'production' const mode = import.meta.env.MODE as EnvMode3.2 数字类型处理
自动转换数字类型:
const port = Number(import.meta.env.VITE_PORT) // 带默认值的便捷方法 function getNumber(key: EnvKey, defaultValue = 0) { return Number(import.meta.env[key] || defaultValue) }4. 工程化实践
4.1 多环境配置
结合.env文件命名规则:
.env.development .env.production定义环境专属类型:
interface DevelopmentEnv extends ImportMetaEnv { VITE_DEBUG: boolean } interface ProductionEnv extends ImportMetaEnv { VITE_SENTRY_DSN: string }4.2 类型生成脚本
通过脚本自动生成类型声明:
# 扫描.env文件生成类型 awk -F= '/^VITE_/ {print "readonly", $1": string"}' .env >> src/env.d.ts5. 常见问题排查
5.1 类型不生效检查清单
- 确认文件路径为
src/env.d.ts - 检查tsconfig包含
"types": ["vite/client"] - 重启IDE确保类型更新
5.2 动态变量处理
对于动态生成的变量名:
function getEnv(key: string) { return import.meta.env[key as EnvKey] }6. 性能优化
6.1 常量提取
避免重复访问env对象:
// 启动时一次性读取 const config = { api: import.meta.env.VITE_API_URL, timeout: Number(import.meta.env.VITE_TIMEOUT) } as const6.2 Tree Shaking
通过常量定义帮助构建工具优化:
export const __DEV__ = import.meta.env.DEV这种模式在构建时会被替换为字面量。