Dominando o `window` no TypeScript: como adicionar sua própria propriedade sem quebrar o código

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que adicionar uma propriedade ao window é uma dor de cabeça para todo desenvolvedor TypeScript?



Imagine a situação: você está escrevendo uma aplicação SPA moderna em TypeScript. Tudo vai bem, até que surge a necessidade de salvar um estado global ou integrar com um script externo (por exemplo, analytics, mapas ou gateway de pagamento). Você escreve:



window.myAppConfig = { apiKey: '123' };


E então o TypeScript mostra um erro vermelho: "Property 'myAppConfig' does not exist on type 'Window & typeof globalThis'". Familiar? Essa pergunta já acumulou milhares de visualizações no Stack Overflow, e hoje não vamos apenas dar uma solução pronta, mas também olhar sob o capô do TypeScript para entender por que isso acontece e como lidar com isso de forma elegante e segura.



Neste artigo, vamos abordar várias abordagens — desde "gambiarras" para iniciantes até padrões profissionais usados por desenvolvedores seniores. Vamos lá!



Sob o capô: por que o TypeScript reclama de window.myProp?



Para entender o problema, precisamos lembrar que o TypeScript é uma extensão do JavaScript que adiciona tipagem estática. O objeto window no navegador é um objeto global que possui um tipo predefinido (Window). Esse tipo está descrito nas bibliotecas padrão do TypeScript (lib.dom.d.ts) e inclui todas as propriedades padrão: document, location, setTimeout e centenas de outras.



Quando você tenta atribuir window.myProp, o TypeScript verifica: "Essa propriedade existe na interface Window?". Não — então é erro. Isso é uma proteção contra erros de digitação e poluição acidental do escopo global. Mas o que fazer se você intencionalmente quiser estender o window?



Método 1: O mais simples, mas perigoso — as any



A primeira opção que vem à mente de um iniciante é simplesmente "calar" o TypeScript usando uma conversão de tipo:



(window as any).myAppConfig = { apiKey: '123' };


Vantagens: rápido, funciona, não requer definições adicionais.

Desvantagens: você perde todas as vantagens do TypeScript. Sem autocomplete, sem verificação de tipos. Se você acidentalmente escrever myAppConfigg — não haverá erro, mas a aplicação quebrará em tempo de execução. É como desligar os airbags do carro — dá para dirigir, mas é arriscado.



Quando usar: apenas para prototipagem rápida ou se você tiver certeza de que a propriedade será usada uma única vez e depois removida.



Método 2: Estendendo a interface global (Interface Merging)



O TypeScript suporta fusão de interfaces (declaration merging). Este é o mecanismo chave que permite "adicionar" novas propriedades ao tipo Window já existente. Para isso, você precisa declarar uma interface com o mesmo nome no escopo global.



Crie um arquivo global.d.ts (ou adicione em qualquer arquivo .d.ts do seu projeto):



// global.d.tsinterface Window {    myAppConfig: {        apiKey: string;        debugMode?: boolean;    };    myAnalyticsFunction: (event: string, data: object) => void;}


Agora você pode escrever:



window.myAppConfig = { apiKey: '123' };window.myAnalyticsFunction('page_view', { page: '/home' });

// TypeScript sugerirá que apiKey é uma stringconsole.log(window.myAppConfig.apiKey); // ✅ Sem erros


Como funciona sob o capô? O TypeScript automaticamente mescla (merge) todas as declarações de interfaces com o mesmo nome. Se em lib.dom.d.ts já existe interface Window { ... }, sua interface com o mesmo nome simplesmente adicionará novas propriedades a ela. Isso é chamado de glob

Blogs

Book Recommendations