Come impostare esplicitamente una nuova proprietà su `finestra` di tipo dattiloscritto?

StackOverflow https://stackoverflow.com//questions/12709074

  •  13-12-2019
  •  | 
  •  

Domanda

I Configurazione dei nomi globali per i miei oggetti impostando esplicitamente una proprietà su window.

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

Destinatari sottolinea MyNamespace e lamenta che:

.

La proprietà 'mynamespace' non esiste sul valore della finestra del tipo " QUALSIASI "

Posso effettuare il codice del codice dichiarando MyNamespace come una variabile ambientale e lasciando cadere l'esplicita window, ma non voglio farlo.

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};
.

Come posso tenere window in là e rendere il dattiloscritto felice?

Come una nota laterale trovo particolarmente divertente che dattilvestisct si lamenta da quando mi dice che window è di tipo any che sicuramente può contenere qualsiasi cosa.

È stato utile?

Soluzione

Ho appena trovato la risposta a questo in un'altra risposta domanda di stackoverflow .

declare global {
    interface Window { MyNamespace: any; }
}

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

Fondamentalmente è necessario estendere l'interfaccia window esistente per dirlo alla tua nuova proprietà.

Altri suggerimenti

Per tenerlo dinamico, basta usare:

(<any>window).MyNamespace
.

As of Dypescript ^ 3.4.3 Questa soluzione non funziona più

o ...

Puoi semplicemente digitare:

window['MyNamespace']
.

E non avrai un errore di compilazione e funziona uguale a digitando window.MyNamespace

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

Ecco cosa ho fatto:

(window as any).MyNamespace
.

La risposta accettata è ciò che ho usato, ma con dattiloscritto 0.9. * Non funziona più.La nuova definizione dell'interfaccia Window sembra sostituire completamente la definizione incorporata, invece di aumentarlo.

Ho portato a farlo invece:

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

declare var window: MyWindow;
.

Aggiornamento: con dattiloscritto 0.9.5 La risposta accettata sta funzionando nuovamente.

Global sono "malvagia" :), Penso che il modo migliore per avere anche la portabilità è:

Prima esporti l'interfaccia: (ad esempio: ./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}
.

Secondo importare

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

Terza finestra Global Var Global con customWindow

declare let window: CustomWindow;
.

In questo modo non hai anche la linea rossa in IDE diversi se si utilizza con gli attributi esistenti dell'oggetto della finestra, quindi alla fine prova:

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

testato con dattilografo 2.4.x e più nuovo!

Se è necessario estendere l'oggetto window con un tipo personalizzato che richiede l'utilizzo di import è possibile utilizzare il seguente metodo:

window.d.ts

import MyInterface from './MyInterface';

declare global {
    interface Window {
        propName: MyInterface
    }
}
.

Vedere "Aumento globale" nella sezione "Dichiarazione di fusione" del manuale: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#Global-Augmentation

Non ho bisogno di farlo molto spesso, l'unico caso che ho avuto quando usi 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';

Per chi usa il Angular CLI è semplice:

SRC / PolyFills.ts

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

my-personalizzato-utils.ts

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

Se stai usando Intellij, è necessario anche modificare la seguente impostazione nell'IDE prima di ritirare i tuoi nuovi PolyFills:

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

La maggior parte delle altre risposte non è perfetta.

    .
  • alcuni di loro sopprimono l'inferenza del tipo per il negozio.
  • Alcuni degli altri si preoccupano solo della variabile globale come spazio dei nomi, ma non come interfaccia / classe

I incontro anche il problema simile questa mattina. Ho provato così tante "soluzioni" su così, ma nessuno di loro non produce alcun errore di tipo ASSOLUTAMENTE e abilitare il tipo di trigger che salta in IDE (WebStorm o Vscode).

Infine, da qui

.

https://github.com/microsoft/typescript/issues/3180# Issuecomment-102523512

, trovo una soluzione ragionevole per Attaccare le digitali per la variabile globale che funge da interfaccia / classe e namespace sia .

L'esempio è sotto:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}
.

Ora, il codice sopra unisce le digitazioni del Namespace MyNamespace e interfaccia MyNamespace nel Global Variable myNamespace (la proprietà della finestra).

Dopo aver trovato risposte in giro, penso che questa pagina potrebbe essere utile. https://www.typescriptlang.org/docs/handbook/Declaration-Merging.html # Global-aumentation Non sono sicuro della storia della fusione della dichiarazione, ma spiega perché il seguente potrebbe funzionare.

declare global {
    interface Window { MyNamespace: any; }
}

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

Ecco come farlo, se stai usando dattiloscritto definizione gestore !

npm install typings --global
.

Crea typings/custom/window.d.ts:

interface Window {
  MyNamespace: any;
}

declare var window: Window;
.

Installare la tua digitazione personalizzata:

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

Fatto, usalo ! dattiloscritto non si lamenta più:

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

Se si utilizza dattiloscritto 3.x, potresti essere in grado di omettere la parte declare global nelle altre risposte e invece solo utilizzare:

interface Window {
  someValue: string
  another: boolean
}
.

Questo ha funzionato con me quando si utilizza DiscriptScript 3.3, WebPack e Tssint.

Typscript non esegue TypeCheck su proprietà stringa.

window["newProperty"] = customObj;
.

Idealmente, dovrebbe essere evitato lo scenario variabile globale.Lo uso a volte per eseguire il debug di un oggetto nella console del browser.

Per riferimento (questa è la risposta corretta):

Dentro un file di definizione .d.ts

type MyGlobalFunctionType = (name: string) => void
.

Se lavori nel browser, Aggiungere membri al contesto della finestra del browser mediante riapertura dell'interfaccia della finestra:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}
.

Stessa idea per Nodejs:

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

Ora dichiari la variabile principale (che vivrà in realtà sulla finestra o globale)

declare const myGlobalFunction: MyGlobalFunctionType;
.

Poi in un normale file .ts, ma importato come effetto collaterale, effettivamente implementarlo:

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

e infine lo usano altrove nel codice Codice, con:

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

myGlobalFunction("Kevin");
.

Crea un'interfaccia personalizzata estende la finestra e aggiungi la proprietà personalizzata come facoltativa.

Quindi, consentono di consultare l'interfaccia personalizzata che utilizza l'interfaccia personalizzata, ma valutata con la finestra originale.

È lavorato con il dattiloscritto@3.1.3.

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {} 
.

Per coloro che desiderano impostare una proprietà calcolata o dinamica sull'oggetto window, troverai che non è possibile con il metodo declare global.Per chiarire per questo caso di utilizzo

window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature
.

Potresti tentare di fare qualcosa come questo

declare global {
  interface Window {
    [DyanmicObject.key]: string; // error RIP
  }
}
.

Quanto sopra si verificherà però.Questo perché in dattiloscritto, le interfacce non giocano bene con proprietà calcolate e lancerà un errore come

A computed property name in an interface must directly refer to a built-in symbol
.

Per aggirare questo, puoi andare con il suggerimento di fusione di window a <any> in modo da poter fare

(window as any)[DynamicObject.key]
.

Volevo usarlo in una libreria angolare (6) oggi e mi ci è voluto un po 'per far funzionare questo come previsto.

Affinché la mia biblioteca utilizzare le dichiarazioni che ho dovuto utilizzare l'esposizione d.ts per il file che dichiara le nuove proprietà dell'oggetto globale.

Così alla fine, il file è finito con qualcosa come:

/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.

Questo ha fatto per me.Spero che questo aiuti.

Prima è necessario dichiarare l'oggetto della finestra nell'ambito corrente.
. Perché il dattiloscritto vorrebbe conoscere il tipo dell'oggetto.
. Poiché l'oggetto della finestra è definito da qualche altra parte non è possibile ridefinarlo.
. Ma puoi dichiararlo come segue: -

declare var window: any;
.

Questo non ridefinirà l'oggetto finestra o non creerà un'altra variabile con il nome window.
. Ciò significa che la finestra è definita da qualche altra parte e ti stai solo facendo riferimento nell'ambito corrente.

Allora puoi riferirti al tuo oggetto mynamespace semplicemente da: -

window.MyNamespace
.

O puoi impostare la nuova proprietà sull'oggetto window semplicemente da: -

window.MyNamespace = MyObject
.

E ora il dattilga non si lamenterà.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top