Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як типізувати глобальні змінні й доповнити Window чи ImportMetaEnv?

Інколи значення справді глобальне: дані, які сервер вбудовує в сторінку (window.App = {...} з Blade), скрипт аналітики, змінні середовища збирача. TypeScript треба про них розповісти.

Доповнення Window з файлу-модуля:

// src/types/global.d.ts
import type { User } from '../models';

declare global {
  interface Window {
    App: {
      locale: string;
      user: User | null;
    };
    dataLayer: unknown[];
  }
}

export {};

declare global працює лише у файлі-модулі (з import/export). export {} наприкінці перетворює файл на модуль, якщо інших імпортів немає.

У файлі-скрипті (без імпортів) глобальні оголошення пишуть без обгортки:

// globals.d.ts
interface Window {
  dataLayer: unknown[];
}
declare const __APP_VERSION__: string;   // значення, підставлене збирачем (define у Vite)

Змінні середовища Vite:

// src/vite-env.d.ts
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_APP_NAME: string;
  readonly VITE_API_URL: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

Тепер import.meta.env.VITE_API_URL має тип рядка, а друкарська помилка в назві - помилку компіляції.

process.env у Node.js - через простір імен NodeJS:

declare global {
  namespace NodeJS {
    interface ProcessEnv {
      DATABASE_URL: string;
      NODE_ENV: 'development' | 'production' | 'test';
    }
  }
}

Пастки:

  • оголошення - не гарантія. TypeScript повірить, що window.App.user існує, навіть якщо сервер його не передав. Для даних ззовні краще перевірка під час виконання (схема Zod) і чесні типи з | undefined;
  • змінні середовища оголошені як string, але під час виконання можуть бути відсутні - валідація конфігурації при старті надійніша за самі типи;
  • файл не в include - найчастіша причина, чому оголошення «не бачить» компілятор;
  • var у declare global додає властивість і в globalThis, а let/const - ні; для globalThis.x потрібен саме var.

Докладніше в документації: Злиття оголошень: глобальне доповнення

Схожі питання