Hoe stel je expliciet een nieuwe eigenschap in op `window` in TypeScript?

Ik stel globale naamruimten in voor mijn objecten door expliciet een eigenschap in te stellen op window.

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

TypeScript onderstreept MyNamespaceen klaagt dat:

De eigenschap ‘MyNamespace’ bestaat niet op waarde van het type ‘window’
elke”

Ik kan de code laten werken door MyNamespaceals een ambient-variabele te declareren en het windowexpliciet te laten vallen, maar dat wil ik niet.

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

Hoe kan ik windowdaarin houden en TypeScript gelukkig maken?

Als een kanttekening vind ik het vooral grappig dat TypeScript klaagt, omdat het me vertelt dat windowvan het type anyis dat absoluut alles kan bevatten.


Antwoord 1, autoriteit 100%

Ik heb zojuist het antwoord hierop gevonden in het antwoord van een andere Stack Overflow-vraag.

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

Kortom, u moet de bestaande window-interface uitbreiden om het over uw nieuwe eigendom te vertellen.


Antwoord 2, autoriteit 46%

Om het dynamisch te houden, gebruik je gewoon:

(<any>window).MyNamespace

Merk op dat dit mogelijk niet werkt met TSX omdat de compiler zou kunnen denken dat de <any>een TSX-element is. Bekijk dit antwoordvoor typebevestiging die compatibel is met TSX.


Antwoord 3, autoriteit 24%

Gebruik je Svelte of TSX? Geen van de andere antwoorden werkte voor mij.

Dit is wat ik deed:

(window as any).MyNamespace

Antwoord 4, autoriteit 20%

Vanaf TypeScript ^3.4.3 werkt deze oplossing niet meer

Of…

je kunt gewoon typen:

window['MyNamespace']

En je krijgt geen compileerfout en het werkt hetzelfde als het typen van window.MyNamespace.


Antwoord 5, autoriteit 10%

Globalen zijn “slecht” 🙂 Ik denk dat de beste manier om ook de draagbaarheid te hebben is:

Eerst exporteert u de interface: (bijvoorbeeld ./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

Ten tweede importeer je

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

Ten derde, cast het globale variabele venster met CustomWindow:

declare let window: CustomWindow;

Op deze manier heb je ook geen rode lijn in een andere IDE als je deze gebruikt met bestaande attributen van het windowobject, dus probeer op het einde:

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

Getest met TypeScript 2.4.x en nieuwste!


Antwoord 6, autoriteit 7%

Het geaccepteerde antwoord is wat ik vroeger gebruikte, maar met TypeScript 0.9.* werkt het niet meer. De nieuwe definitie van de window-interface lijkt de ingebouwde definitie volledig te vervangen, in plaats van deze aan te vullen.

In plaats daarvan ben ik dit gaan doen:

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

Update: met typescript 0.9.5 Het geaccepteerde antwoord werkt weer.


7, Autoriteit 5%

Als u het venster windowmet een aangepast type wilt verlengen dat het gebruik van importvereist, kunt u de volgende methode gebruiken:

venster.d.ts

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

Zie Global Augmentation in de ‘verklaring Het samenvoegen van ‘sectie van het handboek.


8, Autoriteit 4%

De meeste andere antwoorden zijn niet perfect.

  • Sommigen onderdrukken gewoon de Type-inferentie voor Show.
  • Sommige van de anderen geven alleen om globale variabelen als naamruimten, maar niet als interfaces / klassen

Ik ben vanmorgen ook een soortgelijk probleem tegengekomen. Ik heb zoveel ‘oplossingen’ geprobeerd op stapeloverloop, maar geen van hen produceerde absoluut geen type fouten en gaf het triggeringstype in de IDE (WebStorm of visuele studio-code ).

Ten slotte, van Sta moduledefinities toe om als wereldwijde variabelen te worden gedeclareerd # 3180

Ik vond een redelijke oplossing voor Bevestig types voor een wereldwijde variabele die fungeert als interface / klasse en naamruimte, zowel .

Het voorbeeld is hieronder:

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

De bovenstaande code versmelt de types van naamruimte MyNamespaceen interface MyNamespacein de globale variabele MyNamespace(het eigendom van venster ).


9, Autoriteit 4%

Maak een bestand met de naam global.d.ts, bijvoorbeeld /src/@types/global.d.ts, en definieer vervolgens een interface zoals:

interface Window {
  myLib: any
}

Referentie: Global .d .ts


10, Autoriteit 3%

Ik hoef dit niet vaak te doen. Het enige geval dat ik heb gehad was bij het gebruik van redux devtools met middleware.

Ik deden gewoon:

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

of u zou kunnen doen:

let myWindow = window as any;

En dan myWindow.myProp = 'my value';


Antwoord 11, autoriteit 2%

Nadat ik antwoorden heb gevonden, denk ik dat deze pagina nuttig kan zijn:

Globale augmentatie

Ik ben niet zeker van de geschiedenis van het samenvoegen van verklaringen, maar het verklaart waarom het volgende zou kunnen werken.

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

Antwoord 12

TypeScript voert geen typecontrole uit op tekenreekseigenschappen.

window["newProperty"] = customObj;

Idealiter zou het globale variabele scenario vermeden moeten worden. Ik gebruik het soms om fouten op te sporen in een object in de browserconsole.


Antwoord 13

Met behulp van create-react-app v3.3 vond ik dat de gemakkelijkste manier om dit te bereiken was om het window-type uit te breiden in de automatisch gegenereerde react-app-env.d.ts:

interface Window {
    MyNamespace: any;
}

Antwoord 14

Hier leest u hoe u dit doet, als u TypeScript Definition Managergebruikt!

npm install typings --global

Maak typings/custom/window.d.ts:

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

Installeer uw aangepaste typen:

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

Klaar! Gebruik het! TypeScript zal niet meer klagen:

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

Antwoord 15

Als u TypeScript 3.x gebruikt, kunt u het gedeelte declare globalweglaten in de andere antwoorden en in plaats daarvan gewoon gebruiken:

interface Window {
  someValue: string
  another: boolean
}

Dit werkte bij mij bij het gebruik van TypeScript 3.3, Webpacken TSLint.


Antwoord 16

Gebruik

window["MyNamespace"] = window["MyNamespace"] || {};

zou goed moeten zijn omdat het een string-eigenschap gebruikt, maar als je echt een gescheiden venster wilt hebben en je code wilt ordenen, kun je het window-object uitbreiden:

interface MyNamespacedWindow extends Window {
    MyNamespace: object;
}
declare var window: MyNamespacedWindow;

17

Ter referentie (dit is het juiste antwoord):

in een .d.tsdefinitiebestand

type MyGlobalFunctionType = (name: string) => void

Als u in de browser werkt, voegt u leden toe aan de venstercontext van de browser door de interface van het venster opnieuw te openen:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

hetzelfde idee voor knooppunt.js:

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

Nu declareren u de root-variabele (die daadwerkelijk op venster of globaal zal wonen):

declare const myGlobalFunction: MyGlobalFunctionType;

Dan in een gewone .tsbestand, maar geïmporteerd als bijwerking, implementeert u het echt:

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

en gebruik het uiteindelijk elders in de codebase, met:

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

18

Voor degenen die een berekende of dynamische eigenschap willen instellen op het windowObject, vindt u dat niet mogelijk met de declare globalMethod. Om te verduidelijken voor dit gebruik Case

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

U kunt proberen iets als deze

te doen

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

Het bovenstaande is echter fout. Dit komt omdat Intypescript-interfaces niet goed spelen met berekende eigenschappen en een fout gooien als

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

Om dit te realiseren, kunt u met de suggestie van gieten windownaar <any>, zodat u

kunt doen

(window as any)[DynamicObject.key]

19

Ik wilde dit vandaag in een Angular (6)-bibliotheek gebruiken en het kostte me een tijdje om dit te laten werken zoals verwacht.

Om mijn bibliotheek declaraties te laten gebruiken, moest ik de extensie d.tsgebruiken voor het bestand dat de nieuwe eigenschappen van het globale object declareert.

Dus uiteindelijk eindigde het bestand met zoiets als:

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

Als het eenmaal is gemaakt, vergeet dan niet om het zichtbaar te maken in uw public_api.ts.

Dat deed het voor mij.


Antwoord 20

Volledig & Kort antwoord

1- Voeg typeRootseigenschap toe aan tsconfig.json:

{
  "compilerOptions": {
    ...
    "typeRoots": ["src/@types", "node_modules/@types"]
    ...
  }
}

2- Verleng windowtype

// file: src/@types/global.d.ts
declare global {
    interface Window { customProperty: <type>; }
}

Antwoord 21

(window as { test: string } & Window & typeof globalThis).test = `Hello World`;

Antwoord 22

// In typings.d.ts(is Global)
export declare global {
    interface Window {
        __PUBLIC__: string;
    }
}


Antwoord 23

TypeScript voorkomt toegang tot een object zonder een type toe te wijzen dat de gewenste eigenschap heeft of
al toegewezen aan any, dus u kunt optionele ketens gebruiken:

window?.MyNamespace =  'value'

Other episodes