टाइपस्क्रिप्ट में 'इंस्टाफॉफ़' मुझे त्रुटि क्यों देता है "'फू' केवल एक प्रकार को संदर्भित करता है, लेकिन यहां एक मूल्य का उपयोग किया जा रहा है?"


93

मैंने यह कोड लिखा था

interface Foo {
    abcdef: number;
}

let x: Foo | string;

if (x instanceof Foo) {
    // ...
}

लेकिन टाइपस्क्रिप्ट ने मुझे यह त्रुटि दी:

'Foo' only refers to a type, but is being used as a value here.

ये क्यों हो रहा है? मैंने सोचा था कि instanceofयह जांच सकता है कि मेरे मूल्य में एक दिया प्रकार है, लेकिन टाइपस्क्रिप्ट ऐसा नहीं लगता है।


नीचे दिए गए उत्तर को देखें @ 4castle। अन्यथा, आप सही हैं, मैं इसे बनाऊंगा Foo | string
डेनियल रोसेनवेसर


और चेक के संभावित डुप्लिकेट यदि वेरिएबल यूनियन में एक विशिष्ट इंटरफ़ेस प्रकार है (मैं वास्तव में इसे एक हाथ से हथौड़ा नहीं करना चाहता हूं)
सेरेब्रस

@ जेनी ओ'रेली, अब यह निश्चित रूप से एक नकली की नकल है!
मार्केसे डे

जवाबों:


105

क्या चल रहा है

मुद्दा यह है कि instanceofजावास्क्रिप्ट से एक निर्माण है, और जावास्क्रिप्ट में, दाईं ओर के ऑपरेंड के लिए instanceofएक मूल्य की उम्मीद है । विशेष रूप से, x instanceof Fooजावास्क्रिप्ट में यह देखने के लिए रनटाइम चेक करेगा कि क्या Foo.prototypeप्रोटोटाइप श्रृंखला में कहीं भी मौजूद है x

हालाँकि, टाइपस्क्रिप्ट में, interfaceकोई उत्सर्जन नहीं है। इसका मतलब है कि रनटाइम पर Fooन तो Foo.prototypeमौजूद है, इसलिए यह कोड निश्चित रूप से विफल हो जाएगा।

टाइपस्क्रिप्ट आपको यह बताने की कोशिश कर रहा है कि यह कभी काम नहीं कर सकता । Fooकेवल एक प्रकार है, यह एक मूल्य नहीं है!

"इसके बजाय मैं क्या कर सकता हूं instanceof?"

आप प्रकार गार्ड और उपयोगकर्ता-परिभाषित प्रकार गार्ड में देख सकते हैं

"लेकिन अगर मैं सिर्फ एक से बदल क्या interface एक करने के लिए class?"

आप एक से स्विच करने के लिए परीक्षा हो सकती है interfaceएक करने के लिए classहै, लेकिन आप टाइपप्रति की संरचनात्मक प्रकार प्रणाली में है कि (जहां बातें मुख्य रूप से कर रहे हैं एहसास होना चाहिए आधारित आकार ), आप किसी भी एक वस्तु किसी वर्ग के रूप में ही आकार है कि उत्पादन कर सकते हैं:

class C {
    a: number = 10;
    b: boolean = true;
    c: string = "hello";
}

let x = new C()
let y = {
    a: 10, b: true, c: "hello",
}

// Works!
x = y;
y = x;

इस मामले में, आपके पास xऔर yवह एक ही प्रकार का है, लेकिन यदि आप instanceofकिसी एक का उपयोग करने का प्रयास करते हैं , तो आपको दूसरे पर विपरीत परिणाम मिलेगा। तो instanceofनहीं होगा वास्तव में आप बहुत प्रकार यदि आप टाइपप्रति में संरचनात्मक प्रकार का लाभ उठा रहे बारे में बताएं।


2
मुझे अपने लिए एक जगह लेने के लिए उम्र लग गई होगी!
मैथ्यू लेटन

इसलिए मूल रूप से मुझे उस उत्तर से विचार नहीं मिला जो साथ जाना बेहतर है। कक्षा? क्योंकि आपने इसे विस्तृत किया है। लेकिन उसी समय उलझन में थे जब आपने "आप शायद लुभाए" का उल्लेख किया था। तो क्या होगा अगर मुझे सभी संपत्तियों की तुलना करनी है और न केवल संपत्ति को तैरना है जैसा कि टाइप गार्ड के लिए डॉक्स में है?
हाफवेबडेव

8
यहां मुख्य बिंदु यह है कि instanceofकक्षाओं के साथ काम करता है, इंटरफेस नहीं। सोचा कि जोर देने की जरूरत है।
अकार्बनिक

5

एक इंटरफ़ेस के साथ रनटाइम पर टाइप चेकिंग करने के लिए , टाइप गार्ड्स का उपयोग किया जाता है , यदि आपके द्वारा चेक किए जाने वाले इंटरफेस में अलग-अलग गुण / फ़ंक्शन हैं।

उदाहरण

let pet = getSmallPet();

if ((pet as Fish).swim) {
    (pet as Fish).swim();
} else if ((pet as Bird).fly) {
    (pet as Bird).fly();
}

क्या होगा अगर मैं बतख के बारे में सीखता हूं और अपने बर्ड इंटरफेस में फ़ंक्शन तैरना () जोड़ता हूं? क्या प्रत्येक पालतू जानवर को एक प्रकार के गार्ड में मछली के रूप में वर्गीकृत नहीं किया जाएगा? और अगर मेरे पास तीन इंटरफ़ेस हैं जिनमें से प्रत्येक में तीन फ़ंक्शन हैं और एक दूसरे इंटरफेस के साथ दो ओवरलैप हैं?
काइज़ जूल

1
@Kayz यदि आपके पास ऐसे गुण / कार्य नहीं हैं जो किसी इंटरफ़ेस को विशिष्ट रूप से पहचानते हैं, तो आप वास्तव में उन्हें अलग नहीं कर सकते। आपका पालतू जानवर जो वास्तव में एक हो सकता है Duck, आप इसे संरक्षित करते हैं Fish, लेकिन जब आप आह्वान करते हैं तब भी कोई रनटाइम अपवाद नहीं होता है swim()। सुझाव दें कि आप सामान्य स्तर का 1 स्तर बनाते हैं (उदाहरण के लिए Swimmable) और swim()वहां आप कार्य करते हैं, तब टाइप गार्ड अभी भी अच्छा दिखता है ((pet as Swimmable).swim
ली ची कीम

टाइपकास्टिंग को रोकने के लिए आप 'swim' in petस्थिति का उपयोग कर सकते हैं। यह एक उपसमुच्चय के पास इसे सीमित कर देगाswim परिभाषित (पूर्व: Fish | Mammal)
Akxe

2

डैनियल रोसेनवेसर सही और बांका हो सकता है लेकिन मुझे ऐसा लगता है कि उसके जवाब में संशोधन करना। एक्स के उदाहरण की जांच करना पूरी तरह से संभव है, कोड स्निपेट देखें।

लेकिन यह x = y असाइन करना समान रूप से आसान है। अब x, C का उदाहरण नहीं होगा क्योंकि y में केवल C की आकृति थी।

class C {
a: number = 10;
b: boolean = true;
c: string = "hello";
}

let x = new C()
let y = {
    a: 10, b: true, c: "hello",
}

console.log('x is C? ' + (x instanceof C)) // return true
console.log('y is C? ' + (y instanceof C)) // return false
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.