Come imposti esplicitamente una nuova proprietà su `window` in TypeScript?

Ho impostato gli spazi dei nomi globali per i miei oggetti impostando esplicitamente una proprietà sulla window .

 window.MyNamespace = window.MyNamespace || {}; 

TypeScript sottolinea MyNamespace e si lamenta che:

La proprietà ‘MyNamespace’ non esiste sul valore di tipo ‘window’ any ”

Posso far funzionare il codice dichiarando MyNamespace come una variabile ambientale e facendo cadere l’esplicitazione della window ma non voglio farlo.

 declare var MyNamespace: any; MyNamespace = MyNamespace || {}; 

Come posso mantenere la window lì e rendere felice TypeScript?

Come nota a margine trovo particolarmente divertente il fatto che TypeScript si lamenta poiché mi dice che la window è di tipo any che sicuramente può contenere qualsiasi cosa.

Per mantenerlo dinamico, usa semplicemente:

 (window).MyNamespace 

Ho appena trovato la risposta a questa domanda in un’altra domanda di StackOverflow .

 declare global { interface Window { MyNamespace: any; } } window.MyNamespace = window.MyNamespace || {}; 

Fondamentalmente è necessario estendere l’interfaccia della window esistente per raccontarla sulla nuova proprietà.

O…

puoi semplicemente digitare:

 window['MyNamespace'] 

e non si ottiene un errore di compilazione e funziona allo stesso modo di digitare window.MyNamespace

Usando TSX? Nessuna delle altre risposte stava funzionando per me.

Ecco cosa ho fatto:

 (window as any).MyNamespace 

La risposta accettata è ciò che usavo, ma con TypeScript 0.9. * Non funziona più. La nuova definizione dell’interfaccia Window sembra sostituire completamente la definizione integrata, invece di aumentarla.

Ho preso a fare questo invece:

 interface MyWindow extends Window { myFunction(): void; } declare var window: MyWindow; 

AGGIORNAMENTO: Con TypeScript 0.9.5 la risposta accettata sta funzionando di nuovo.

Se è necessario estendere l’object window con un tipo personalizzato che richiede l’utilizzo import è ansible utilizzare il seguente metodo:

window.d.ts

 import MyInterface from './MyInterface'; declare global { interface Window { propName: MyInterface } } 

Vedi ‘Global Augmentation’ nella sezione ‘Dichiarazione di unione’ del manuale: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation

Globali sono “cattivi” :), penso che il modo migliore per avere anche la portabilità sia:

Per prima cosa esportate l’interfaccia: (ad es .: ./custom.window.ts)

 export interface CustomWindow extends Window { customAttribute: any; } 

Secondo, importa

 import {CustomWindow} from './custom.window.ts'; 

Finestra var globale del terzo cast con CustomWindow

 declare let window: CustomWindow; 

In questo modo non hai anche la linea rossa in IDE diversi se usi gli attributi esistenti dell’object window, quindi alla fine prova:

 window.customAttribute = 'works'; window.location.href = '/works'; 

Testato con Typescript 2.4.x

Ecco come farlo, se stai usando TypeScript Definition Manager !

 npm install typings --global 

Crea typings/custom/window.d.ts :

 interface Window { MyNamespace: any; } declare var window: Window; 

Installa la tua digitazione personalizzata:

 typings install file:typings/custom/window.d.ts --save --global 

Fatto, usalo ! Typescript non si lamenterà più:

 window.MyNamespace = window.MyNamespace || {}; 

La maggior parte delle altre risposte non sono perfette.

  • Alcuni di loro sopprimono solo l’inferenza del tipo per negozio.
  • Ad alcuni altri interessa solo la variabile globale come spazio dei nomi, ma non come interfaccia / class

Incontro anche il problema simile questa mattina. Ho provato così tante “soluzioni” su SO, ma nessuna di esse produce assolutamente errori di tipo e abilita il trigger di tipo che salta in IDE (webstorm o vscode).

Finalmente, da qui

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

, Trovo una soluzione ragionevole per albind i tipi per la variabile globale che funge da interfaccia / class e spazio dei nomi entrambi .

Esempio è qui sotto:

 // typings.d.ts declare interface Window { myNamespace?: MyNamespace & typeof MyNamespace } declare interface MyNamespace { somemethod?() } declare namespace MyNamespace { // ... } 

Ora, il codice sopra unisce i tipi di spazio dei nomi MyNamespace e interfaccia MyNamespace nella variabile globale myNamespace (la proprietà della finestra).

Non ho bisogno di farlo molto spesso, l’unico caso che ho avuto è stato l’utilizzo di Redux Devtools con il middleware.

Ho semplicemente fatto:

 const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; 

O potresti fare:

let myWindow = window as any;

e poi myWindow.myProp = 'my value';

Se stai utilizzando la CLI Angolare , è davvero semplice (testato su CLI RC.0):

src / polyfills.ts

 declare global { interface Window { myCustomFn: () => void; } } 

my-custom-utils.ts

 window.myCustomFn = function () { ... }; 

Sto usando IntelliJ, quindi ho anche avuto bisogno di cambiare la seguente impostazione nell’IDE prima che i miei nuovi polifraggi fossero raccolti:

 > File > Settings > Languages & Frameworks > TypeScript > check 'Use TypeScript Service'. 

Per riferimento (questa è la risposta corretta):

All’interno di un file di definizione .d.ts

 type MyGlobalFunctionType = (name: string) => void 

Se lavori nel browser, aggiungi membri al contesto della finestra del browser riaprendo l’interfaccia di Windows:

 interface Window { myGlobalFunction: MyGlobalFunctionType } 

Stessa idea per NodeJS:

 declare module NodeJS { interface Global { myGlobalFunction: MyGlobalFunctionType } } 

Ora dichiari la variabile root (che sarà effettivamente visibile sulla finestra o globale)

 declare const myGlobalFunction: MyGlobalFunctionType; 

Quindi, in un normale file .ts , ma importato come effetto collaterale, lo si implementa effettivamente:

 global/* or window */.myGlobalFunction = function (name: string) { console.log("Hey !", name); }; 

E infine usalo altrove nel codebase, con uno:

 global/* or window */.myGlobalFunction("Kevin"); myGlobalFunction("Kevin"); 

Dopo aver trovato le risposte in giro, penso che questa pagina potrebbe essere utile. https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation Non sono sicuro della cronologia della fusione delle dichiarazioni, ma spiega perché potrebbe funzionare quanto segue.

 declare global { interface Window { MyNamespace: any; } } window.MyNamespace = window.MyNamespace || {}; 

Volevo usarlo in una libreria Angular (6) oggi e mi ci è voluto un po ‘per farlo funzionare come previsto.

Per fare in modo che la mia libreria usasse le dichiarazioni ho dovuto usare l’estensione d.ts per il file che dichiara le nuove proprietà dell’object globale.

Alla fine, il file ha finito con qualcosa di simile:

/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts

Una volta creato, non dimenticare di esporlo nel tuo public_api.ts .

Che ha fatto per me. Spero che questo ti aiuti.