आप टाइपस्क्रिप्ट में 'विंडो' पर स्पष्ट रूप से एक नई संपत्ति कैसे सेट करते हैं?


619

मैं स्पष्ट रूप से एक संपत्ति सेट करके अपनी वस्तुओं के लिए वैश्विक नामस्थान सेट करता हूं window

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

टाइपस्क्रिप्ट रेखांकित करता है MyNamespaceऔर शिकायत करता है कि:

संपत्ति 'MyNamespace' किसी भी प्रकार की 'विंडो' के मान पर मौजूद नहीं है

मैं MyNamespaceएक परिवेश चर के रूप में घोषणा करके और खोजकर्ता को छोड़ने के द्वारा कोड का काम कर सकता हूं, windowलेकिन मैं ऐसा नहीं करना चाहता।

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

मैं कैसे windowवहाँ रख सकते हैं और टाइपस्क्रिप्ट को खुश कर सकते हैं?

एक साइड नोट के रूप में, मुझे यह विशेष रूप से मजेदार लगता है कि टाइपस्क्रिप्ट शिकायत करता है क्योंकि यह मुझे बताता है कि windowवह प्रकार का है anyजिसमें निश्चित रूप से कुछ भी हो सकता है।


जवाबों:


690

बस एक और StackOverflow प्रश्न के उत्तर में इसका उत्तर मिला

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

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

मूल रूप से आपको windowअपनी नई संपत्ति के बारे में बताने के लिए मौजूदा इंटरफ़ेस का विस्तार करना होगा ।


11
विंडो में कैपिटल W पर ध्यान दें। इसने मुझे उलझा दिया।
अंज

2
मुझे यह tsc 1.0.1.0 के साथ संकलन करने के लिए नहीं मिला। ब्लेक मिशेल के जवाब ने मेरे लिए काम किया, हालाँकि।
पैट

43
ज्ञात हो कि यह केवल एक अलग .d.tsफाइल में घोषित होने पर काम करता है । .tsआयात और निर्यात का उपयोग करने वाली फ़ाइल में उपयोग किए जाने पर यह काम नहीं करता है। इस जवाब को देखें ।
carduth

36
declare global { interface Window { ... } }टाइपप्रति 2.5.2 के साथ काम करता है, के लिए कोई जरूरत नहीं .d.tsफ़ाइल जैसा कि ऊपर उल्लेख
tanguy_k

2
पहले टाइपस्क्रिप्ट ने मुझे बताया: error TS1234: An ambient module declaration is only allowed at the top level in a file.जब मैंने इसे फ़ाइल के शीर्ष पर रखा, तो उसने उस त्रुटि को ठीक कर दिया, इसलिए आपको ऐसा करना पड़ सकता है।
ज़ेल्फिर कल्टस्टाहल

397

इसे गतिशील रखने के लिए, बस उपयोग करें:

(<any>window).MyNamespace

9
किसी भी विचार कैसे एक tsx फ़ाइल में ऐसा करने के लिए?
--साल

2
@ स्मार्टिन: <a> यह स्पष्ट करता है, इसलिए यह ठीक काम करता है, मुझे विश्वास है। अन्य: यदि आप रिएक्ट या अन्य JSX वातावरण के साथ टाइपस्क्रिप्ट का उपयोग कर रहे हैं (परिणामस्वरूप TSX सिंटैक्स) तो आपको asइसके बजाय उपयोग करना होगा <>। नीचे @ david-boyd का उत्तर देखें
डॉन

30
मुझे (विंडो को किसी भी रूप में) का उपयोग करना पड़ा। मेमसैनस्पेस
अहमद

इसी तरह this-return (<any> this)['something in scope']
हांकना

1
मुझे उस लाइन पर tslint को निष्क्रिय करना पड़ा है/* tslint:disable */
माइकल यगूदेव

197

TYPESCRIPT के रूप में ^ 3.4.3 इस समाधान कोई लंबा काम नहीं करता है

या ...

आप बस टाइप कर सकते हैं:

window['MyNamespace']

और आपको एक संकलित त्रुटि नहीं मिलेगी और यह टाइपिंग के समान काम करता है window.MyNamespace


15
लेकिन आप शायद एक tslint त्रुटि प्राप्त करेंगे ... यदि आपके पास एक है
smnbbrv

69
यह पूरी तरह से मजबूत टाइपिंग के सामने उड़ जाता है, टाइपस्क्रिप्ट के पीछे का पूरा विचार।
d512

18
@ user1334007 ग्लोबल्स का उपयोग भी करता है। हालांकि, कुछ विरासत कोड को इसकी आवश्यकता होती है।
nathancahill

3
@ रमेश window['MyNamespace']()(सिर्फ कोष्ठक जोड़ें)
iBaff

6
"यह पूरी तरह से मजबूत टाइपिंग के सामने उड़ता है, टाइपस्क्रिप्ट के पीछे का पूरा विचार।" अच्छा!
कोड़ी

188

TSX का उपयोग कर रहे हैं? अन्य कोई भी उत्तर मेरे लिए काम नहीं कर रहा था।

यहाँ मैंने क्या किया है:

(window as any).MyNamespace

4
(<any> window).MyNamespaceवास्तव में उसी के रूप में
दिमित्री Parzhitsky

44
TSX का उपयोग करते समय यह समान है, क्योंकि <any>JSX के रूप में व्याख्या की जाती है, न कि एक प्रकार की डाली।
जेक बून

1
धन्यवाद @ डेविड, इसने नए क्रिएट रिएक्ट ऐप और टाइपस्क्रिप्ट संस्करण के साथ एक आकर्षण की तरह काम किया, इससे पहले यह काम कर रहा था: (<any> विंडो) .MyNamespace, लेकिन अब यह नए टाइपस्क्रिप्ट संस्करण 3.5.x में टूट रहा है।
जिग्नेश रावल

खिड़की के रूप में किसी भी? फिर आप टाइपस्क्रिप्ट का उपयोग क्यों करेंगे? बस जावास्क्रिप्ट x का उपयोग करें)
MarcoLe

71

स्वीकृत उत्तर वह है जो मैं उपयोग करता था, लेकिन टाइपस्क्रिप्ट 0.9 के साथ। * यह अब काम नहीं करता है। Windowइंटरफ़ेस की नई परिभाषा बिल्ट-इन परिभाषा को पूरी तरह से बदलने के बजाय, इसे बढ़ाने के लिए लगती है।

मैंने इसके बजाय इसे करने के लिए लिया है:

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

declare var window: MyWindow;

अद्यतन: टाइपस्क्रिप्ट 0.9.5 के साथ स्वीकृत जवाब फिर से काम कर रहा है।


2
यह टाइपस्क्रिप्ट 2.0.8 द्वारा उपयोग किए गए मॉड्यूल के साथ भी काम करता है। उदाहरण: export default class MyClass{ foo(){ ... } ... } interface MyWindow extends Window{ mc: MyClass } declare var window: MyWindow window.mc = new MyClass() इसके बाद आप क्रोम देव टूल्स कंसोल से foo () कह सकते हैं जैसे mc.foo()
मार्टिन माजूस्की

यदि आप किसी चीज़ को वैश्विक घोषित नहीं करना चाहते हैं तो यह बहुत अच्छा जवाब है। दूसरी तरफ, आपको अपनी ज़रूरत की declare var...हर फ़ाइल में कॉल करना होगा।
puce

इस दृष्टिकोण के लिए प्लस एक क्योंकि इस मामले में आप अन्य पैकेजों के साथ संघर्ष नहीं करते हैं जो मोनोरपो में वैश्विक विंडो का विस्तार करते हैं।
दिमित्री सोरिन

धन्यवाद! सबसे अच्छा जवाब IMO। एक व्यक्ति को Windowइस तथ्य के लिए ओवरराइड नहीं करना चाहिए कि यह एक वेनिला खिड़की नहीं है। बस जाँच को रोकने या TS को मूर्ख बनाने की कोशिश करना भी ऐसा करने का तरीका नहीं है।
रटगर विल्म्स

यह टीएस 3.6 के रूप में काम नहीं करता है, दुर्भाग्य से
जैकब सोदरलंड

65

ग्लोबल "बुराई" :), मुझे लगता है कि पोर्टेबिलिटी का सबसे अच्छा तरीका यह भी है:

सबसे पहले आप इंटरफ़ेस निर्यात करते हैं: (उदाहरण के लिए :/custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

दूसरा आप आयात करें

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

CustomWindow के साथ तीसरी डाली वैश्विक संस्करण विंडो

declare let window: CustomWindow;

इस तरह आपके पास अलग-अलग आईडीई में लाल रेखा भी नहीं है यदि आप विंडो ऑब्जेक्ट की मौजूद विशेषताओं के साथ उपयोग करते हैं, तो अंत में कोशिश करें:

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

टाइपस्क्रिप्ट 2.4.x और नवीनतम के साथ परीक्षण किया गया!


1
आप इस बात का विस्तार करना चाहते हैं कि ग्लोबल्स बुराई क्यों हैं। हमारे मामले में हम विंडो ऑब्जेक्ट पर एक गैर मानकीकृत एपीआई का उपयोग कर रहे हैं। यह अभी के लिए पॉलीफ़िल्ड है। क्या यह बुरी तरह से बुराई है?
मैथिज्स सीजर

1
@MathijsSegers मुझे विशेष रूप से आपका मामला नहीं पता है लेकिन .. ग्लोबल्स के बारे में बुराई केवल जावास्क्रिप्ट के बारे में नहीं है .. हर भाषा में है .. कुछ कारण हैं: - आप अच्छी तरह से डिजाइन पैटर्न लागू नहीं कर सकते हैं - मेमोरी और प्रदर्शन मुद्दा (आप उन्हें हर जगह रखें, स्ट्रिंग ऑब्जेक्ट को कुछ संलग्न करने का प्रयास करें और देखें कि जब आप नया स्ट्रिंग करते हैं तो क्या होता है) - कोड पर साइड इफेक्ट का नाम टकराव होता है .. (विशेषकर जावास्क्रिप्ट पर जो async प्रकृति है) मैं जारी रख सकता हूं लेकिन मुझे लगता है कि आप छवि बना सकते हैं बाकी ...
onalbi

1
@onabi मैं सचमुच ब्राउज़र की एक विशेषता के बारे में बात कर रहा हूँ। यह ब्राउज़र के बाद से विश्व स्तर पर उपलब्ध है। आप वास्तव में सुझाव देंगे कि वैश्विक परिभाषाओं के लिए जाना अभी भी गलत है? मेरा मतलब है कि हम पोनफिल्स को लागू कर सकते हैं, लेकिन यह ब्राउजर को ब्लोट करेगा जो वास्तव में फीचर का समर्थन करता है (जैसे फुलस्क्रीन एपी)। मैंने कहा कि मुझे विश्वास नहीं है कि सभी ग्लोबल्स बुरे पद हैं।
मैथिज्स सीजर

2
@MathijsSegers मेरी राय में वैश्विक वैरिएबल का उपयोग करने या संशोधित करने से बचना चाहिए जहां हम कर सकते हैं .. यह सच है कि ब्राउज़र के मौजूद होने के बाद विंडो उपलब्ध है लेकिन यह भी सच है कि हर समय म्यूटेशन में था .. इसलिए यदि उदाहरण के लिए हम अब परिभाषित करते हैं window.feature = 'फ़ीचर'; और यह कोड पर बड़े पैमाने पर उपयोग किया जाता है .. क्या होता है अगर window.feature सभी कोड पर ब्राउज़रों द्वारा जोड़ा जाता है यह सुविधा ओवरराइड है .. वैसे भी मैंने अपने वाक्य का स्पष्टीकरण दिया है कि आपके खिलाफ नहीं जाना है .. संबंध ...
onalbi

48

यदि आपको windowकिसी कस्टम प्रकार के साथ ऑब्जेक्ट को विस्तारित करने की आवश्यकता है, जिसके लिए importआपको निम्न विधि का उपयोग करने की आवश्यकता हो सकती है:

window.d.ts

import MyInterface from './MyInterface';

declare global {
    interface Window {
        propName: MyInterface
    }
}

हैंडबुक के 'घोषणा विलय' अनुभाग में 'ग्लोबल ऑग्मेंटेशन' देखें: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global- उद्घाटन


43

कोणीय सीएलआई का उपयोग करने वालों के लिए यह सीधा है:

src / polyfills.ts

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

मेरी-कस्टम utils.ts

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

यदि आप IntelliJ का उपयोग कर रहे हैं, तो आपको अपनी नई पॉलीफ़िल लेने से पहले IDE में निम्नलिखित सेटिंग को बदलना होगा:

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

1
declare globalचाल है, और यह जवाब वास्तव में कोणीय सीएलआई के लिए विशिष्ट नहीं है ...
अविंद्र गोलचरण

31

मुझे बहुत बार ऐसा करने की आवश्यकता नहीं है, मेरे पास एकमात्र ऐसा मामला है जब मिडवेवेयर के साथ Redux Devtools का उपयोग किया गया था।

मैंने बस किया:

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

या आप कर सकते हैं:

let myWindow = window as any;

और फिर myWindow.myProp = 'my value';


1
इस स्थिति में आप npm पैकेज भी स्थापित कर सकते हैं, जिसमें सभी परिभाषाएँ हैं - जैसा कि डॉक्स में निर्दिष्ट है
bbrinx

आप ऐसा कर सकते हैं, लेकिन इस प्रश्न का उत्तर नहीं है, बल्कि एक वैकल्पिक हल
Vitalij

इसके लिए धन्यवाद, मैं टाइप करने के तहत ठीक से redux टूल को सक्षम कर सकता हूं (किसी भी रूप में विंडो का उपयोग करके) .__ REDUX_DEVTOOLS_EXTENSION__ && (किसी भी रूप में विंडो) .__ REDUX_DEVTOOLS_EXTENSION__ () ()
danivicario

20

अन्य उत्तर में से अधिकांश सही नहीं हैं।

  • उनमें से कुछ सिर्फ दुकान के लिए प्रकार की धारणा को दबाते हैं।
  • दूसरों में से कुछ केवल नाम के रूप में वैश्विक चर की परवाह करते हैं, लेकिन इंटरफ़ेस / वर्ग के रूप में नहीं

मैं आज सुबह भी इसी तरह की समस्या से जूझ रहा हूं। मैंने एसओ पर इतने सारे "समाधान" की कोशिश की, लेकिन उनमें से कोई भी पूरी तरह से कोई त्रुटि नहीं पैदा करता है और आईडीई (वेबस्टॉर्म या vscode) में टाइपिंग जंपिंग को सक्षम करता है।

अंत में, यहाँ से

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

, मैं वैश्विक चर के लिए टाइपिंग संलग्न करने के लिए एक उचित समाधान ढूंढता हूं जो इंटरफ़ेस / वर्ग और नामस्थान दोनों के रूप में कार्य करता है

उदाहरण नीचे है:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

अब, ऊपर दिया गया कोड वैश्विक चर (विंडो की संपत्ति) में नेमस्पेस MyNamespaceऔर इंटरफ़ेस के टाइपिंग को मर्ज करता है ।MyNamespacemyNamespace


2
धन्यवाद - यह केवल वही है जो आप एक परिवेशी गैर-मॉड्यूल संदर्भ में उपयोग कर सकते हैं।
टायलर सेबेस्टियन

18

चारों ओर उत्तर खोजने के बाद, मुझे लगता है कि यह पृष्ठ सहायक हो सकता है। https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation घोषणा विलय के इतिहास के बारे में निश्चित नहीं है, लेकिन यह बताता है कि निम्नलिखित क्यों काम कर सकता है।

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

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

13

यदि आप टाइपस्क्रिप्ट परिभाषा प्रबंधक का उपयोग कर रहे हैं, तो यह कैसे करें !

npm install typings --global

बनाएँ typings/custom/window.d.ts:

interface Window {
  MyNamespace: any;
}

declare var window: Window;

अपनी कस्टम टाइपिंग स्थापित करें:

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

हो गया, इसका उपयोग करें ! टाइपस्क्रिप्ट अब शिकायत नहीं करेगा:

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

1
FWIW typingsटाइपप्रति 2.0 (मध्य 2016) के साथ अप्रचलित बनाया गया था, और मालिक द्वारा संग्रहीत किया गया है।
mrm

13

टाइपस्क्रिप्ट स्ट्रिंग प्रॉपर्टीज पर टाइपकास्ट नहीं करता है।

window["newProperty"] = customObj;

आदर्श रूप से, वैश्विक चर परिदृश्य से बचा जाना चाहिए। मैं इसे कभी-कभी ब्राउज़र कंसोल में किसी ऑब्जेक्ट को डीबग करने के लिए उपयोग करता हूं।



8

यदि आप टाइपस्क्रिप्ट 3.x का उपयोग कर रहे हैं, तो आप declare globalअन्य उत्तरों में भाग को छोड़ सकते हैं और इसके बजाय केवल उपयोग कर सकते हैं:

interface Window {
  someValue: string
  another: boolean
}

टाइपस्क्रिप्ट 3.3, वेबपैक और TSLint का उपयोग करते समय इसने मेरे साथ काम किया।


में काम नहीं करता है ^3.4.3। इस उत्तर ने मेरे लिए काम किया stackoverflow.com/a/42841166/1114926
ग्रीन

7

संदर्भ के लिए (यह सही उत्तर है):

एक .d.tsपरिभाषा फ़ाइल के अंदर

type MyGlobalFunctionType = (name: string) => void

यदि आप ब्राउज़र में काम करते हैं, तो आप विंडो के इंटरफ़ेस को फिर से खोलकर सदस्यों को ब्राउज़र के विंडो संदर्भ में जोड़ते हैं:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

NodeJS के लिए एक ही विचार:

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

अब आप रूट वेरिएबल घोषित करते हैं (जो वास्तव में विंडो या ग्लोबल पर लाइव होगा)

declare const myGlobalFunction: MyGlobalFunctionType;

फिर एक नियमित .tsफ़ाइल में, लेकिन साइड-इफ़ेक्ट के रूप में आयातित, आप वास्तव में इसे लागू करते हैं:

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

और अंत में इसे कोडबेस में कहीं और इस्तेमाल करें:

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

myGlobalFunction("Kevin");

धन्यवाद, यह सबसे अच्छा उदाहरण है जो मैंने पाया, और अच्छी तरह से काम कर रहा हूं।
निक जी।

6

एक कस्टम इंटरफ़ेस बनाएँ विंडो फैली हुई है और वैकल्पिक के रूप में अपनी कस्टम संपत्ति जोड़ें।

फिर, customWindow को कस्टम इंटरफ़ेस का उपयोग करने दें, लेकिन मूल विंडो के साथ मूल्यवान है।

यह typecript@3.1.3 के साथ काम किया है।

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {} 

5

उन लोगों के लिए जो windowऑब्जेक्ट पर एक गणना या गतिशील संपत्ति सेट करना चाहते हैं , आप पाएंगे कि declare globalविधि के साथ संभव नहीं है । इस उपयोग के मामले को स्पष्ट करने के लिए

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

आप ऐसा कुछ करने का प्रयास कर सकते हैं

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

हालांकि उपरोक्त त्रुटि होगी। ऐसा इसलिए होता है क्योंकि टाइपस्क्रिप्ट में, इंटरफेस गणना वाले गुणों के साथ अच्छी तरह से नहीं खेलता है और एक त्रुटि को फेंक देगा

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

इस के आसपास पाने के लिए आपको कास्टिंग के सुझाव है साथ जा सकते हैं windowकरने के लिए <any>तो आप क्या कर सकते हैं

(window as any)[DynamicObject.key]

3
यह 2019 है।
क्वर्टी

4

Create-react-app v3.3 का उपयोग करके मैंने इसे प्राप्त करने का सबसे आसान तरीका पाया Windowकि ऑटो-जेनरेट किए गए प्रकार का विस्तार करना है react-app-env.d.ts:

interface Window {
    MyNamespace: any;
}

3

पहले आपको विंडो ऑब्जेक्ट को वर्तमान दायरे में घोषित करने की आवश्यकता है।
क्योंकि टाइपस्क्रिप्ट ऑब्जेक्ट के प्रकार को जानना चाहेंगे।
चूंकि विंडो ऑब्जेक्ट कहीं और परिभाषित किया गया है इसलिए आप इसे फिर से परिभाषित नहीं कर सकते।
लेकिन आप इसे इस प्रकार घोषित कर सकते हैं: -

declare var window: any;

यह विंडो ऑब्जेक्ट को फिर से परिभाषित नहीं करेगा या यह नाम के साथ एक और चर नहीं बनाएगा window
इसका मतलब है कि विंडो को कहीं और परिभाषित किया गया है और आप इसे वर्तमान दायरे में संदर्भित कर रहे हैं।

तब आप अपने MyNamespace ऑब्जेक्ट को बस द्वारा संदर्भित कर सकते हैं: -

window.MyNamespace

या आप नई प्रॉपर्टी को windowऑब्जेक्ट पर बस द्वारा सेट कर सकते हैं : -

window.MyNamespace = MyObject

और अब टाइपस्क्रिप्ट शिकायत नहीं करेगा।


क्या मैं यह जानना चाहता हूं कि आपके उपयोग का मामला यह जानना चाहता है कि कहां windowपरिभाषित किया गया है?
13:55 पर Mav55

2

मैं आज एक एंगुलर (6) लाइब्रेरी में इसका इस्तेमाल करना चाहता था और मुझे उम्मीद के मुताबिक काम करने में थोड़ा समय लगा।

मेरी लाइब्रेरी के लिए घोषणाओं का उपयोग करने के लिए मुझे उस d.tsफ़ाइल के लिए एक्स्टेंशन का उपयोग करना था जो वैश्विक ऑब्जेक्ट के नए गुणों की घोषणा करता है।

तो अंत में, फ़ाइल कुछ इस तरह समाप्त हुई:

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

एक बार बनाने के बाद, इसे अपने में उजागर करना न भूलें public_api.ts

वो मेरे लिए किया गया। उम्मीद है की यह मदद करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.