环境变量与全局类型

环境变量的重要性

在现代前端工程化实践中,环境变量(Environment Variables)扮演着至关重要的角色。它们允许我们在不同的部署环境(开发、测试、生产等)中使用不同的配置,而无需修改代码。TypeScript作为JavaScript的超集,为我们提供了更强大的工具来处理环境变量。

TypeScript中的环境变量处理

1. 声明环境变量类型

在TypeScript项目中,我们首先需要声明环境变量的类型。这通常通过创建一个env.d.ts文件来实现:

typescript 复制代码
// src/env.d.ts
declare namespace NodeJS {
  interface ProcessEnv {
    readonly NODE_ENV: 'development' | 'production' | 'test';
    readonly API_BASE_URL: string;
    readonly SENTRY_DSN?: string;
    readonly GA_TRACKING_ID?: string;
  }
}

这种声明方式确保了我们在代码中访问process.env时能够获得类型提示和类型检查。

2. 使用dotenv管理环境变量

在实际开发中,我们通常使用dotenv库来管理环境变量:

typescript 复制代码
import dotenv from 'dotenv';

dotenv.config();

// 现在可以安全地访问环境变量
const apiUrl = process.env.API_BASE_URL;

为了确保类型安全,我们可以创建一个配置验证函数:

typescript 复制代码
function getConfig(env: NodeJS.ProcessEnv) {
  return {
    env: env.NODE_ENV || 'development',
    apiUrl: env.API_BASE_URL,
    sentryDsn: env.SENTRY_DSN,
    gaTrackingId: env.GA_TRACKING_ID,
  };
}

const config = getConfig(process.env);

全局类型的定义与管理

1. 定义全局类型

在大型TypeScript项目中,我们经常需要定义一些全局可用的类型。这可以通过在global.d.ts文件中扩展全局命名空间来实现:

typescript 复制代码
// src/global.d.ts
declare global {
  interface Window {
    __APP_CONFIG__: {
      version: string;
      buildDate: string;
    };
  }

  type Nullable<T> = T | null;
  type Maybe<T> = T | undefined;
}

2. 组织全局类型

对于复杂的项目,建议将全局类型分类管理:

复制代码
types/
  ├── global.d.ts       # 基础全局类型
  ├── api.d.ts          # API相关类型
  ├── components.d.ts   # 组件相关类型
  └── utils.d.ts        # 工具类型

3. 使用全局工具类型

TypeScript提供了一些内置的全局工具类型,我们可以充分利用它们:

typescript 复制代码
// 使用内置工具类型
type PartialUser = Partial<User>;
type ReadonlyUser = Readonly<User>;
type UserKeys = keyof User;

工程化实践建议

  1. 严格的环境变量检查:在应用启动时验证必需的环境变量是否已设置
  2. 类型安全的配置对象:将环境变量转换为强类型的配置对象
  3. 区分运行时和编译时环境变量:明确哪些变量在构建时注入,哪些在运行时可用
  4. 全局类型的文档化:为重要的全局类型添加文档注释
  5. 避免过度使用全局类型:只在真正需要全局可访问时才定义全局类型

示例:完整的环境配置方案

typescript 复制代码
// src/config.ts
interface AppConfig {
  env: 'development' | 'production' | 'test';
  api: {
    baseUrl: string;
    timeout: number;
  };
  features: {
    analytics: boolean;
    sentry: boolean;
  };
}

export function createConfig(env: NodeJS.ProcessEnv): AppConfig {
  return {
    env: env.NODE_ENV as AppConfig['env'] || 'development',
    api: {
      baseUrl: env.API_BASE_URL || 'http://localhost:3000',
      timeout: parseInt(env.API_TIMEOUT || '5000', 10),
    },
    features: {
      analytics: !!env.GA_TRACKING_ID,
      sentry: !!env.SENTRY_DSN,
    },
  };
}

const config = createConfig(process.env);
export default config;

通过这种结构化的方式,我们既保证了类型安全,又实现了配置的集中管理,为大型TypeScript项目的工程化实践奠定了坚实的基础。