Как явно добавить новое свойство объекту window в TypeScript
Правильный способ: расширение интерфейса Window через declaration merging
Лучший и самый типобезопасный способ — использовать механизм declaration merging (слияние объявлений) в TypeScript. Вы расширяете существующий интерфейс Window, добавляя в него свои свойства.
Создайте файл global.d.ts (или любой файл с расширением .d.ts) в корне вашего проекта и объявите в нём:
// global.d.ts
interface Window {
myCustomProperty: string;
sessionId: number;
isAppReady: boolean;
}
После этого TypeScript автоматически "подхватит" это объявление, и вы сможете использовать свойства напрямую:
// main.ts
window.myCustomProperty = 'hello world';
console.log(window.myCustomProperty); // работает без ошибок
window.sessionId = 12345;
window.isAppReady = true;
Почему это работает?
В TypeScript интерфейсы с одинаковыми именами автоматически объединяются (merge). Когда вы объявляете interface Window в файле .d.ts, TypeScript добавляет ваши свойства к уже существующему определению Window из стандартной библиотеки (lib.dom.d.ts).
Важные нюансы:
- Файл должен быть .d.ts — это файл объявлений, который не генерирует код, а только добавляет типы.
- Глобальная область видимости — объявление будет доступно во всех файлах проекта без дополнительных импортов.
- Типизация сохраняется — TypeScript будет проверять типы ваших свойств, автодополнение в IDE будет работать.
- Необязательные свойства — если свойство может отсутствовать, используйте
?::
interface Window {
myCustomProperty?: string;
}
Альтернативный подход с модулями
Если вы используете модули (ES modules) и хотите избежать глобального загрязнения, можно объявить свойство через declare global внутри модуля:
// utils/windowExtensions.ts
export {};
declare global {
interface Window {
myCustomProperty: string;
}
}
// Теперь можно использовать window.myCustomProperty
// Но это объявление будет видно только после импорта этого файла
Чего делать НЕ стоит:
(window as any).prop— убивает типизацию, вы теряете автодополнение и проверку типовwindow['prop'] = value— то же самое, что и выше- Переопределять
Windowчерезtype— это не сработает, так какtypeне поддерживает declaration merging
Этот подход используется в крупных проектах (Angular, React, Vue) и считается стандартом для расширения глобальных объектов в TypeScript.
<<Быстрый вариант через type assertion с защитой
Если вам нужно добавить свойство быстро и вы не хотите создавать отдельный файл с объявлениями, можно использовать более безопасную версию as any — через промежуточный интерфейс:
interface CustomWindow {
myCustomProperty: string;
}
const customWindow = window as unknown as CustomWindow;
customWindow.myCustomProperty = 'hello';
// Или однострочник:
(window as unknown as { myCustomProperty: string }).myCustomProperty = 'hello';
Когда это применимо:
- Для быстрого прототипирования
- Когда свойство используется в одном месте
- В небольших скриптах без строгой архитектуры
Минусы:
- Не расширяет глобальный тип — в других файлах свойство не будет известно
- Приходится каждый раз приводить тип
- Легко забыть про приведение и получить ошибку
Для production-проектов всё же рекомендую первый подход с .d.ts файлом — он чище и масштабируемее.
Ответов пока нет.
Войдите чтобы оставить ответ