Wie legt man in TypeScript explizit eine neue Eigenschaft für „window“ fest?

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

  •  13-12-2019
  •  | 
  •  

Frage

Ich richte globale Namespaces für meine Objekte ein, indem ich explizit eine Eigenschaft festlege window.

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

TypeScript unterstreicht MyNamespace und beschwert sich darüber:

Die Eigenschaft 'mynamesspace' existiert nicht im Wert des Typs 'Fenster' Any ".

Ich kann dafür sorgen, dass der Code funktioniert, indem ich ihn deklariere MyNamespace als Umgebungsvariable und Löschen der window Explizitheit, aber das möchte ich nicht tun.

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

Wie kann ich behalten window rein und TypeScript glücklich machen?

Nebenbei bemerkt finde ich es besonders lustig, dass sich TypeScript beschwert, da es mir das sagt window ist vom Typ any was definitiv alles enthalten kann.

War es hilfreich?

Lösung

Habe gerade die Antwort darauf gefunden Die Antwort auf eine weitere StackOverflow-Frage.

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

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

Grundsätzlich müssen Sie das Bestehende erweitern window Schnittstelle, um es über Ihre neue Immobilie zu informieren.

Andere Tipps

Um es dynamisch zu halten, verwenden Sie einfach:

(<any>window).MyNamespace

AB TYPESCRIPT ^3.4.3 FUNKTIONIERT DIESE LÖSUNG NICHT MEHR

Oder...

Sie können einfach Folgendes eingeben:

window['MyNamespace']

und Sie erhalten keinen Kompilierungsfehler und es funktioniert genauso wie beim Tippen window.MyNamespace

Verwenden Sie TSX?Keine der anderen Antworten funktionierte für mich.

Folgendes habe ich getan:

(window as any).MyNamespace

Die akzeptierte Antwort ist die, die ich früher verwendet habe, aber mit TypeScript 0.9.* funktioniert es nicht mehr.Die neue Definition der Window Die Schnittstelle scheint die integrierte Definition vollständig zu ersetzen, anstatt sie zu erweitern.

Ich habe stattdessen Folgendes getan:

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

declare var window: MyWindow;

AKTUALISIEREN: Mit TypeScript 0.9.5 funktioniert die akzeptierte Antwort wieder.

Global sind „böse“ :), ich denke, der beste Weg, auch die Portabilität zu gewährleisten, ist:

Zuerst exportieren Sie die Schnittstelle:(z.B:./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

Zweitens importieren Sie

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

Drittes globales Variablenfenster mit CustomWindow umwandeln

declare let window: CustomWindow;

Auf diese Weise haben Sie nicht auch eine rote Linie in einer anderen IDE, wenn Sie sie mit vorhandenen Attributen eines Fensterobjekts verwenden. Versuchen Sie es also am Ende:

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

Getestet mit Typescript 2.4.x und neu!

Wenn Sie die erweitern müssen window Objekt mit einem benutzerdefinierten Typ, der die Verwendung von erfordert import Sie können die folgende Methode verwenden:

window.d.ts

import MyInterface from './MyInterface';

declare global {
    interface Window {
        propName: MyInterface
    }
}

Siehe „Globale Augmentation“ im Abschnitt „Deklarationszusammenführung“ des Handbuchs: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation

Ich muss das nicht sehr oft tun, der einzige Fall, den ich hatte, war die Verwendung von Redux Devtools mit Middleware.

Ich habe einfach Folgendes getan:

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

Oder Sie könnten Folgendes tun:

let myWindow = window as any;

und dann myWindow.myProp = 'my value';

Für diejenigen, die das verwenden Angular CLI es ist ganz einfach:

src/polyfills.ts

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

my-custom-utils.ts

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

Wenn Sie IntelliJ verwenden, mussten Sie außerdem die folgende Einstellung in der IDE ändern, bevor Ihre neuen Polyfills wirksam werden:

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

Die meisten anderen Antworten sind nicht perfekt.

  • Einige von ihnen unterdrücken einfach die Typinferenz für Shop.
  • Einige andere kümmern sich nur um globale Variablen als Namespace, nicht jedoch um Schnittstellen/Klassen

Ich bin heute Morgen auch auf ein ähnliches Problem gestoßen.Ich habe so viele „Lösungen“ für SO ausprobiert, aber keine davon erzeugt absolut keinen Typfehler und ermöglicht das Auslösen von Typsprüngen in der IDE (Webstorm oder vscode).

Endlich von hier aus

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

, ich finde eine vernünftige Lösung dafür Hängen Sie Typisierungen für globale Variablen an, die sowohl als Schnittstelle/Klasse als auch als Namespace fungieren.

Beispiel ist unten:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

Der obige Code führt nun die Typisierungen des Namespace zusammen MyNamespace und Schnittstelle MyNamespace in die globale Variable myNamespace(die Eigenschaft von Fenster).

Nachdem ich Antworten gefunden habe, denke ich, dass diese Seite hilfreich sein könnte.https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentationIch bin mir über die Geschichte der Zusammenführung von Deklarationen nicht sicher, aber es erklärt, warum das Folgende funktionieren könnte.

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

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

Hier erfahren Sie, wie es geht, wenn Sie es verwenden TypeScript-Definitionsmanager!

npm install typings --global

Erstellen typings/custom/window.d.ts:

interface Window {
  MyNamespace: any;
}

declare var window: Window;

Installieren Sie Ihre benutzerdefinierte Eingabe:

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

Fertig, verwenden Sie es! Typescript wird sich nicht mehr beschweren:

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

Wenn Sie Typescript 3.x verwenden, können Sie möglicherweise darauf verzichten declare global Teil in den anderen Antworten und verwenden Sie stattdessen einfach:

interface Window {
  someValue: string
  another: boolean
}

Dies funktionierte bei mir, als ich Typescript 3.3, WebPack und TSLint verwendete.

Typscript führt keine Typprüfung für Zeichenfolgeneigenschaften durch.

window["newProperty"] = customObj;

Idealerweise sollte das Szenario mit globalen Variablen vermieden werden.Ich verwende es manchmal, um ein Objekt in der Browserkonsole zu debuggen.

Als Referenz (dies ist die richtige Antwort):

In einem .d.ts Definitionsdatei

type MyGlobalFunctionType = (name: string) => void

Wenn Sie im Browser arbeiten, fügen Sie Mitglieder zum Fensterkontext des Browsers hinzu, indem Sie die Schnittstelle des Fensters wiedereröffnen:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

Gleiche Idee für NodeJS:

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

Jetzt deklarieren Sie die Stammvariable (die tatsächlich im Fenster oder global leben wird).

declare const myGlobalFunction: MyGlobalFunctionType;

Dann in einem regulären .ts Datei, aber als Nebeneffekt importiert, implementieren Sie sie tatsächlich:

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

Und schließlich an anderer Stelle in der Codebasis verwenden, entweder mit:

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

myGlobalFunction("Kevin");

Erstellen Sie eine benutzerdefinierte Schnittstelle, die das Fenster erweitert, und fügen Sie Ihre benutzerdefinierte Eigenschaft optional hinzu.

Lassen Sie dann das benutzerdefinierte Fenster die benutzerdefinierte Schnittstelle verwenden, werten Sie es jedoch mit dem Originalfenster aus.

Es hat mit dem Typescript@3.1.3 funktioniert.

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {} 

Für diejenigen, die eine berechnete oder dynamische Eigenschaft festlegen möchten window Objekt, Sie werden feststellen, dass das mit dem nicht möglich ist declare global Methode.Zur Verdeutlichung für diesen Anwendungsfall

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

Sie könnten versuchen, so etwas zu tun

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

Das Obige führt jedoch zu einem Fehler.Dies liegt daran, dass Schnittstellen in Typescript nicht gut mit berechneten Eigenschaften funktionieren und einen Fehler wie „

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

Um dies zu umgehen, können Sie auf den Casting-Vorschlag zurückgreifen window Zu <any> so können Sie es tun

(window as any)[DynamicObject.key]

Ich wollte dies heute in einer Angular (6)-Bibliothek verwenden und es hat eine Weile gedauert, bis es wie erwartet funktionierte.

Damit meine Bibliothek Deklarationen verwenden konnte, musste ich die verwenden d.ts Erweiterung für die Datei, die die neuen Eigenschaften des globalen Objekts deklariert.

Am Ende hatte die Datei also etwas wie:

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

Vergessen Sie nicht, es nach der Erstellung in Ihrem Browser verfügbar zu machen public_api.ts.

Das hat es für mich getan.Hoffe das hilft.

Zuerst müssen Sie das Fensterobjekt im aktuellen Bereich deklarieren.
Denn Typescript möchte den Typ des Objekts wissen.
Da das Fensterobjekt an einer anderen Stelle definiert ist, können Sie es nicht neu definieren.
Aber Sie können es wie folgt deklarieren:-

declare var window: any;

Dadurch wird das Fensterobjekt nicht neu definiert oder es wird keine weitere Variable mit Namen erstellt window.
Das bedeutet, dass das Fenster an einer anderen Stelle definiert ist und Sie nur im aktuellen Bereich darauf verweisen.

Dann können Sie einfach auf Ihr MyNamespace-Objekt verweisen:

window.MyNamespace

Oder Sie können die neue Eigenschaft aktivieren window Objekt einfach durch:-

window.MyNamespace = MyObject

Und jetzt wird sich das Typoskript nicht beschweren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top