टाइपस्क्रिप्ट में चार अलग-अलग पहलू हैं जिनसे आपको अवगत होना चाहिए। सबसे पहले, कुछ परिभाषाएँ:
"लुकिंग ऑब्जेक्ट"
यदि आप यह एनम लिखते हैं:
enum Foo { X, Y }
टाइपस्क्रिप्ट निम्नलिखित वस्तु का उत्सर्जन करेगा:
var Foo;
(function (Foo) {
Foo[Foo["X"] = 0] = "X";
Foo[Foo["Y"] = 1] = "Y";
})(Foo || (Foo = {}));
मैं इसे लुकअप ऑब्जेक्ट के रूप में संदर्भित करूंगा । इसका उद्देश्य दोहरा है: से एक मानचित्रण के रूप में सेवा करने के लिए तार करने के लिए संख्या जब लेखन, जैसे Foo.X
या Foo['X']
, और से एक मानचित्रण के रूप में सेवा करने के लिए संख्या के तार । यह रिवर्स मैपिंग डीबगिंग या लॉगिंग उद्देश्यों के लिए उपयोगी है - आपके पास अक्सर मूल्य होगा 0
या 1
संबंधित स्ट्रिंग प्राप्त करना चाहते हैं "X"
या "Y"
।
"घोषित" या " परिवेश "
टाइपस्क्रिप्ट में, आप उन चीजों को "घोषित" कर सकते हैं जिनके बारे में कंपाइलर को पता होना चाहिए, लेकिन वास्तव में इसके लिए कोड का उत्सर्जन नहीं करना चाहिए। यह तब उपयोगी होता है जब आपके पास jQuery जैसी लाइब्रेरी होती है जो कुछ ऑब्जेक्ट (जैसे $
) को परिभाषित करती है, जिसके बारे में आप टाइप जानकारी चाहते हैं, लेकिन कंपाइलर द्वारा बनाए गए किसी भी कोड की आवश्यकता नहीं है। युक्ति और अन्य दस्तावेज़ीकरण घोषणाओं को संदर्भित करता है जो इस तरह से "परिवेश" के संदर्भ में किया जाता है; यह ध्यान रखना महत्वपूर्ण है कि एक .d.ts
फ़ाइल में सभी घोषणाएं "परिवेश" हैं (या तो एक स्पष्ट declare
संशोधक की आवश्यकता है या यह घोषणा के आधार पर निहित है)।
"इनलाइन किए जाने वाले"
प्रदर्शन और कोड आकार कारणों के लिए, अक्सर संकलित होने पर इसके संख्यात्मक समकक्ष द्वारा प्रतिस्थापित एक एनम सदस्य के संदर्भ के लिए बेहतर होता है:
enum Foo { X = 4 }
var y = Foo.X; // emits "var y = 4";
युक्ति इस प्रतिस्थापन को कॉल करती है, मैं इसे इनलाइनिंग कहूंगा क्योंकि यह कूलर लगता है। कभी-कभी आप यह नहीं चाहेंगे कि एनुम सदस्य, उदाहरण के लिए, क्योंकि एनम एपीआई एपीआई के भविष्य के संस्करण में बदल सकता है।
एनम, वे कैसे काम करते हैं?
आइए, एनम के प्रत्येक पहलू से इसे तोड़ते हैं। दुर्भाग्य से, इन चार खंडों में से प्रत्येक अन्य सभी से शर्तों का संदर्भ देने वाला है, इसलिए आपको संभवतः इस पूरी चीज़ को एक से अधिक बार पढ़ने की आवश्यकता होगी।
गणना बनाम गैर-संगणित (स्थिर)
इनम सदस्यों की गणना की जा सकती है या नहीं। कल्पना गैर-संगणित सदस्यों को निरंतर बुलाती है, लेकिन मैं उन्हें कॉन्स्टेबल के साथ भ्रम से बचने के लिए गैर-संगणित कहूंगा ।
एक गणना किए गए एनम सदस्य वह है जिसका मूल्य संकलन-समय पर ज्ञात नहीं है। गणना किए गए सदस्यों के संदर्भ बेशक, इनलाइन नहीं हो सकते। इसके विपरीत, एक गैर गणना enum सदस्य है जिसका मूल्य एक बार किया जाता है संकलन समय पर जाना जाता है। गैर-गणना वाले सदस्यों के संदर्भ हमेशा इनबिल्ड होते हैं।
कौन से एनुम सदस्यों की गणना की जाती है और कौन से गैर-गणना किए जाते हैं? const
जैसा कि नाम से ही पता चलता है कि पहले एक एनम के सभी सदस्य निरंतर (यानी गैर-गणना वाले) हैं। एक नॉन-कॉस्ट एनम के लिए, यह इस बात पर निर्भर करता है कि आप एंबिएंट (डिक्लेयर) एनम या नॉन-एम्बिएंट एनम को देख रहे हैं या नहीं।
declare enum
(यानी एंबियंट एनम) का एक सदस्य स्थिर होता है यदि और केवल यदि उसका इनिशियलाइज़र हो तो। अन्यथा, यह गणना की जाती है। ध्यान दें कि ए में declare enum
, केवल संख्यात्मक आरंभिकों की अनुमति है। उदाहरण:
declare enum Foo {
X, // Computed
Y = 2, // Non-computed
Z, // Computed! Not 3! Careful!
Q = 1 + 1 // Error
}
अंत में, गैर-घोषित गैर-कॉन्स्टेबल एनमर्स के सदस्यों को हमेशा गणना करने के लिए माना जाता है। हालांकि, उनकी प्रारंभिक अभिव्यक्तियाँ स्थिरांक तक कम हो जाती हैं यदि वे संकलन-समय पर कम्प्यूटेशनल हैं। इसका मतलब है कि गैर-कॉन्स्टेबल एनम सदस्य कभी भी इनबिल्ड नहीं होते हैं (यह व्यवहार टाइपस्क्रिप्ट 1.5 में बदल गया है, नीचे "टाइपस्क्रिप्ट में परिवर्तन" देखें)
const बनाम नॉन-कास्ट
स्थिरांक
एक एनुम घोषणा में संशोधन हो सकता है const
। यदि कोई एनम है const
, तो सभी सदस्य अपने सदस्यों को संदर्भित करते हैं।
const enum Foo { A = 4 }
var x = Foo.A; // emitted as "var x = 4;", always
const enums संकलित होने पर लुकअप ऑब्जेक्ट का उत्पादन नहीं करता है। इस कारण से, Foo
उपरोक्त कोड में एक सदस्य संदर्भ के हिस्से को छोड़कर संदर्भ के लिए एक त्रुटि है । Foo
रनटाइम पर कोई ऑब्जेक्ट मौजूद नहीं होगा।
गैर स्थिरांक
यदि किसी एनुम घोषणा में संशोधन नहीं होता है, तो const
इसके सदस्यों के संदर्भ केवल तभी अंतर्निर्मित होते हैं, यदि सदस्य गैर-गणना वाला होता है। एक नॉन-कॉस्ट, नॉन-डिक्लेयर एनम लुकिंग ऑब्जेक्ट उत्पन्न करेगा।
डिक्लेयर (परिवेश) बनाम नॉन-डिक्लेयर
एक महत्वपूर्ण प्रस्तावना यह है कि declare
टाइपस्क्रिप्ट में एक बहुत विशिष्ट अर्थ है: यह ऑब्जेक्ट कहीं और मौजूद है । यह मौजूदा वस्तुओं का वर्णन करने के लिए है । declare
उन वस्तुओं को परिभाषित करने का उपयोग करना जो वास्तव में मौजूद नहीं हैं, जिनके बुरे परिणाम हो सकते हैं; हम बाद में उन का पता लगाएंगे।
घोषित
ए declare enum
लुकअप ऑब्जेक्ट का उत्सर्जन नहीं करेगा। यदि उन सदस्यों की गणना की जाती है (तो गणना बनाम गैर-गणना पर ऊपर देखें) इसके सदस्यों के संदर्भ उल्लिखित हैं।
यह ध्यान रखना महत्वपूर्ण है कि संदर्भ के अन्य रूपों declare enum
को अनुमति दी जाती है, उदाहरण के लिए यह कोड एक संकलन त्रुटि नहीं है, लेकिन रनटाइम में विफल हो जाएगा :
// Note: Assume no other file has actually created a Foo var at runtime
declare enum Foo { Bar }
var s = 'Bar';
var b = Foo[s]; // Fails
यह त्रुटि "कंपाइलर से झूठ मत बोलो" की श्रेणी में आती है। यदि आपके पास Foo
रनटाइम नाम की कोई वस्तु नहीं है , तो न लिखें declare enum Foo
!
A , declare const enum
से अलग नहीं है const enum
, सिवाय --preserveConstEnums के मामले में (नीचे देखें)।
गैर घोषित
यदि यह नहीं है तो एक गैर-घोषित एनम एक लुकअप ऑब्जेक्ट का उत्पादन करता है const
। ऊपर वर्णित है।
--preserveConstEnums ध्वज
इस ध्वज का ठीक एक प्रभाव है: गैर-घोषित कांस्टेबल एनम लुकअप ऑब्जेक्ट का उत्सर्जन करेगा। Inlining प्रभावित नहीं है। यह डिबगिंग के लिए उपयोगी है।
आम त्रुटियों
सबसे आम गलती यह है कि declare enum
जब एक नियमित रूप से enum
या const enum
अधिक उपयुक्त होगा का उपयोग करें । एक सामान्य रूप यह है:
module MyModule {
// Claiming this enum exists with 'declare', but it doesn't...
export declare enum Lies {
Foo = 0,
Bar = 1
}
var x = Lies.Foo; // Depend on inlining
}
module SomeOtherCode {
// x ends up as 'undefined' at runtime
import x = MyModule.Lies;
// Try to use lookup object, which ought to exist
// runtime error, canot read property 0 of undefined
console.log(x[x.Foo]);
}
सुनहरा नियम याद रखें: कभी declare
चीजें हैं जो वास्तव में मौजूद नहीं है । const enum
यदि आप हमेशा इनलाइनिंग चाहते हैं, या enum
यदि आप लुकिंग ऑब्जेक्ट चाहते हैं तो इसका उपयोग करें ।
टाइपस्क्रिप्ट में परिवर्तन
टाइपस्क्रिप्ट १.४ और १.५ के बीच, व्यवहार में एक परिवर्तन हुआ (देखें https://github.com/Microsoft/TypeScript/issues/2183 ) गैर-घोषित गैर- कॉन्स्टेबल सदस्यों के सभी सदस्यों को गणना के रूप में माना जाए, भले ही वे स्पष्ट रूप से एक शाब्दिक के साथ आरंभिक हैं। यह "बच्चे को अनप्लस" करता है, इसलिए बोलने के लिए, इनलाइनिंग व्यवहार को अधिक अनुमानित और अधिक स्वच्छ const enum
रूप से अवधारणा को नियमित रूप से अलग करना enum
। इस बदलाव से पहले, गैर-कास्ट एनमों के गैर-गणना वाले सदस्यों को अधिक आक्रामक रूप से इनलाइन किया गया था।