टाइपस्क्रिप्ट में ऑब्जेक्ट शाब्दिक परिभाषा


344

टाइपस्क्रिप्ट कक्षाओं में, उदाहरण के लिए, गुणों के प्रकार घोषित करना संभव है:

class className {
  property: string;
};

एक वस्तु शाब्दिक में एक संपत्ति के प्रकार की घोषणा कैसे करें?

मैंने निम्नलिखित कोड की कोशिश की है, लेकिन यह संकलन नहीं करता है:

var obj = {
  property: string;
};

मुझे निम्नलिखित त्रुटि मिल रही है:

मौजूदा स्कोप में 'स्ट्रिंग' नाम मौजूद नहीं है

क्या मैं कुछ गलत कर रहा हूँ या यह एक बग है?

जवाबों:


423

आप बहुत करीब, तो आप सिर्फ प्रतिस्थापित करने की आवश्यकता कर रहे हैं =एक साथ :। आप एक ऑब्जेक्ट प्रकार शाब्दिक (कल्पना अनुभाग 3.5.3 देखें) या एक इंटरफ़ेस का उपयोग कर सकते हैं। ऑब्जेक्ट प्रकार शाब्दिक का उपयोग करना आपके पास क्या है:

var obj: { property: string; } = { property: "foo" };

लेकिन आप एक इंटरफ़ेस का उपयोग भी कर सकते हैं

interface MyObjLayout {
    property: string;
}

var obj: MyObjLayout = { property: "foo" };

14
कलाकारों ऑपरेटर के साथ @ प्यार से DRY (बार-बार खुद को दोहराएं) विकल्प ज्यादा नॉटी लगता है। सिर्फ टिप्पणी करते हुए, नीचा दिखाने वाला नहीं ...
0

मुझे पता है कि यह कुछ समय पहले उत्तर दिया गया है, लेकिन क्या मैं इस धारणा में गलत हूं कि जब क्लास के साथ-साथ गुण भी होते हैं तो क्या मुद्दे पैदा हो सकते हैं? चूंकि कक्षा आरंभ नहीं हुई है और हम केवल गुण प्रदान करते हैं, इसलिए कक्षा पर एक विधि को कॉल करने से एक अशक्त अपवाद हो जाएगा। मूल रूप से, हम जिस वस्तु को वर्ग के रूप में केवल 'कार्य' बनाते हैं क्योंकि हम इसके प्रकार को निर्दिष्ट करते हैं, लेकिन यह वास्तव में उस वर्ग का उदाहरण नहीं है। यानी हमें 'नए' कीवर्ड के साथ क्लास बनाने की जरूरत है। और फिर हम वर्ग 1 में वापस आ गए हैं, क्योंकि हम नई कक्षा () {prop: 1} जैसी कुछ नहीं कर सकते हैं; उदाहरण के लिए, जैसे हम C # में कर सकते हैं।
DeuxAlpha

@DeuxAlpha यह एक इंटरफ़ेस को असाइन कर रहा है , जिसमें विधियाँ नहीं हो सकती हैं। मुझे विश्वास नहीं है कि आप इस तरह एक वर्ग को असाइन कर सकते हैं।
मोगा

कल्पना से लिंक अच्छा होगा :)
ahong

@DeuxAlpha यह एक ऑब्जेक्ट शाब्दिक निर्माण है, न कि एक क्लास ऑब्जेक्ट। इसके अलावा एक इंटरफ़ेस के तरीके हो सकते हैं। यदि आपका इंटरफ़ेस एक विधि को परिभाषित करता है, तो ऑब्जेक्ट शाब्दिक भी इसे परिभाषित करना चाहिए - यह शून्य नहीं होगा। ऑब्जेक्ट शाब्दिक इंटरफ़ेस को परिभाषित करने वाली हर चीज को पूरा करना चाहिए या टाइप सिस्टम एक त्रुटि दिखाएगा।
रिक लव

291

अपडेट 2019-05-15 (बेहतर कोड पैटर्न वैकल्पिक के रूप में)

constअधिक कार्यात्मक कोड से उपयोग और लाभ के कई वर्षों के बाद , मैं ज्यादातर मामलों में नीचे का उपयोग करने के खिलाफ सुझाऊंगा। (जब वस्तुओं का निर्माण करते हैं, तो टाइप सिस्टम को एक विशेष प्रकार में मजबूर करने के बजाय यह अनुमान लगाने के लिए कि अक्सर यह संकेत होता है कि कुछ गलत है)।

इसके बजाय मैं constजितना संभव हो चर का उपयोग करने की सलाह दूंगा और फिर अंतिम चरण के रूप में वस्तु की रचना करूंगा :

const id = GetId();
const hasStarted = true;
...
const hasFinished = false;
...
return {hasStarted, hasFinished, id};
  • यह स्पष्ट टाइपिंग की आवश्यकता के बिना सब कुछ ठीक से टाइप करेगा।
  • फ़ील्ड नामों को फिर से टाइप करने की कोई आवश्यकता नहीं है।
  • यह मेरे अनुभव से सबसे साफ कोड की ओर जाता है।
  • यह कंपाइलर को अधिक राज्य सत्यापन प्रदान करने की अनुमति देता है (उदाहरण के लिए, यदि आप कई स्थानों पर लौटते हैं, तो कंपाइलर यह सुनिश्चित करेगा कि एक ही प्रकार की वस्तु हमेशा लौटा दी जाए - जो आपको प्रत्येक स्थिति में संपूर्ण वापसी मूल्य घोषित करने के लिए प्रोत्साहित करती है - पूरी तरह से स्पष्ट उस मूल्य का आशय)।

जोड़ 2020-02-26

यदि आपको वास्तव में एक प्रकार की आवश्यकता है जिसे आप आलसी रूप से आरंभीकृत कर सकते हैं: निशान यह एक अशक्त संघ प्रकार (अशक्त या प्रकार) है। प्रकार प्रणाली आपको यह सुनिश्चित करने के बिना इसका उपयोग करने से रोकेगी कि इसका मूल्य क्या है।

में tsconfig.json, सुनिश्चित करें कि आप सख्त नल जाँच सक्षम करें:

"strictNullChecks": true

फिर इस पैटर्न का उपयोग करें और आपको आकस्मिक नल / अपरिभाषित पहुंच से बचाने के लिए प्रकार प्रणाली की अनुमति दें:



const state = {
    instance: null as null | ApiService,
    // OR
    // instance: undefined as undefined | ApiService,

};

const useApi = () => {
    // If I try to use it here, the type system requires a safe way to access it

    // Simple lazy-initialization 
    const api = state?.instance ?? (state.instance = new ApiService());
    api.fun();

    // Also here are some ways to only access it if it has value:

    // The 'right' way: Typescript 3.7 required
    state.instance?.fun();

    // Or the old way: If you are stuck before Typescript 3.7
    state.instance && state.instance.fun();

    // Or the long winded way because the above just feels weird
    if (state.instance) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans way
    if (state.instance != null) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans 
    // AND I was told to always use triple === in javascript even with null checks way
    if (state.instance !== null && state.instance !== undefined) { state.instance.fun(); }
};

class ApiService {
    fun() {
        // Do something useful here
    }
}

99% मामलों में नीचे न करें:

अपडेट 2016-02-10 - TSX को हैंडल करने के लिए (धन्यवाद @ जोश)

asTSX के लिए ऑपरेटर का उपयोग करें ।

var obj = {
    property: null as string
};

एक लंबा उदाहरण:

var call = {
    hasStarted: null as boolean,
    hasFinished: null as boolean,
    id: null as number,
};

मूल उत्तर

इस रसीले को बनाने के लिए कास्ट ऑपरेटर का उपयोग करें (वांछित प्रकार के नल को कास्टिंग करके)।

var obj = {
    property: <string> null
};

एक लंबा उदाहरण:

var call = {
    hasStarted: <boolean> null,
    hasFinished: <boolean> null,
    id: <number> null,
};

यह दो भागों (एक प्रकार घोषित करने के लिए, दूसरे को चूक घोषित करने के लिए) से बेहतर है:

var callVerbose: {
    hasStarted: boolean;
    hasFinished: boolean;
    id: number;
} = {
    hasStarted: null,
    hasFinished: null,
    id: null,
};

10
यदि आप TSX (JSX के साथ TS) का उपयोग कर रहे हैं, तो आप कोण ब्रैकेट के नामकरण का उपयोग नहीं कर सकते हैं, इसलिए वे लाइनें कुछ इस तरह की हो जाती हैं, property: null as stringजिसमें महत्वपूर्ण अंतर asऑपरेटर होता है।
जोश

2
@RickLove क्या यह वास्तव में ऑब्जेक्ट वैरिएबल के प्रकार को बाधित करता है, या यह केवल असाइन किए गए प्रकारों को निर्दिष्ट करने का एक तरीका है? दूसरे शब्दों में, callअपने दूसरे उदाहरण में चर को असाइन करने के बाद , क्या आप इसे पूरी तरह से भिन्न प्रकार का असाइन कर सकते हैं?
डैनियल ग्रिसकॉम

3
इसका उत्तर होना चाहिए
ड्रू आर

4
काम नहीं कर रहा। Error:(33, 15) TS2352:Type 'null' cannot be converted to type 'string'.
स्लाइड शो 2

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

31

मुझे आश्चर्य है कि किसी ने भी इसका उल्लेख नहीं किया है, लेकिन आप सिर्फ एक इंटरफेस बना सकते हैं ObjectLiteral, जो key: valueजोड़े के प्रकारों को स्वीकार करता है string: any:

interface ObjectLiteral {
  [key: string]: any;
}

तो आप इसे इस तरह उपयोग करेंगे:

let data: ObjectLiteral = {
  hello: "world",
  goodbye: 1,
  // ...
};

एक अतिरिक्त बोनस यह है कि आप जितनी बार चाहें उतनी वस्तुओं पर इस इंटरफ़ेस का उपयोग कर सकते हैं।

सौभाग्य।


3
यह एक बुरा विचार है, यह प्रकार प्रणाली को बेकार बनाता है। टाइपस्क्रिप्ट का मतलब टाइप सिस्टम को त्रुटियों को रोकने में मदद करना है और टूलींग में बेहतर स्वत: पूर्ण कार्यक्षमता प्रदान करने में मदद करना है - यह मूल रूप से टाइपस्क्रिप्ट के सभी लाभों को अक्षम करता है। उपरोक्त उदाहरण में किसी भी इंटरफ़ेस का उपयोग नहीं करना बेहतर होगा।
रिक लव

1
@ रिकॉल मैं दृढ़ता से असहमत हूं। जब कई गुण वैकल्पिक होते हैं तो यह असाधारण रूप से उपयोगी होता है, लेकिन हम अभी भी सभी प्रकारों को स्पष्ट रूप से परिभाषित करना चाहते हैं (जैसे कि फ़ंक्शन के लिए तर्क युक्त)। इसे सिंटैक्टिक शुगर के रूप में देखा जा सकता है और यह वास्तव में इंटरफेसेस के गुणों के लिए एक प्रसार ऑपरेटर की तरह काम करता है ।
CPHPython

@CPHPython केवल अपने विशिष्ट प्रकारों के साथ वैकल्पिक मापदंडों को निर्दिष्ट क्यों नहीं करते हैं? केवल यह समय समझ में आता है यदि कोड समय पर नाम ज्ञात नहीं हैं (यानी वे डेटाबेस या बाहरी स्रोत से आ रहे हैं)। तर्कों के जटिल संयोजन के लिए भी, यूनियन प्रकार महान काम करते हैं। यदि आप विशिष्ट नामों के खिलाफ कोडिंग कर रहे हैं, तो यदि संभव हो तो उन्हें परिभाषित किया जाना चाहिए। यदि यह केवल डेटा है जो तर्क को प्रभावित नहीं करता है, तो निश्चित रूप से इसे टाइप सिस्टम से बाहर छोड़ दें।
रिक लव

1
@RickLove "कोड समय पर नाम ज्ञात नहीं हैं" -> यह एक अच्छा और व्यावहारिक उदाहरण है, उन कुंजी प्रकारों के मूल्यों को जाना जाता है और वे सभी समान हैं (जैसे स्ट्रिंग )। मन है कि मैं केवल [key: string]भाग के उपयोग की वकालत कर रहा था , मूल्य के प्रकार की परिभाषा के रूप में किसी भी भाग की नहीं ... जो वास्तव में प्रकार की उपयोगिता को बाहर निकाल देगा।
CPHPython

1
यदि मैं स्ट्रिंग और संख्याओं को जोड़ने की अनुमति देना चाहता हूं, तो मैं कैसे जाऊंगा, लेकिन अन्य प्रकार नहीं?
गधेबनाँ

14

यदि आप एक प्रकार का एनोटेशन लिखने की कोशिश कर रहे हैं, तो वाक्य रचना है:

var x: { property: string; } = ...;

यदि आप एक वस्तु शाब्दिक लिखने की कोशिश कर रहे हैं, तो वाक्य रचना है:

var x = { property: 'hello' };

आपका कोड मान स्थिति में एक प्रकार नाम का उपयोग करने का प्रयास कर रहा है।


10
आपकी var x: { property: string; } = ...;एक टीस है! मुझे आशा है कि दीर्घवृत्त के लिए शॉर्टहैंड होने के लिए वैध वाक्यविन्यास था var x: { property: string; } = { property: 'hello' };
जेसन क्लेबन

10

टाइपस्क्रिप्ट में यदि हम ऑब्जेक्ट घोषित कर रहे हैं तो हम निम्नलिखित सिंटैक्स का उपयोग करेंगे:

[access modifier] variable name : { /* structure of object */ }

उदाहरण के लिए:

private Object:{ Key1: string, Key2: number }

7

यदि आप एक विनाशकारी वस्तु शाब्दिक में टाइपिंग जोड़ने की कोशिश कर रहे हैं , उदाहरण के लिए एक फ़ंक्शन के लिए तर्क में, वाक्यविन्यास है:

function foo({ bar, baz }: { bar: boolean, baz: string }) {
  // ...
}

foo({ bar: true, baz: 'lorem ipsum' });

5

यदि आपके गुणों में समान प्रकार है, तो आप पूर्वनिर्धारित उपयोगिता प्रकार का उपयोग कर सकते हैं Record:

type Keys = "property" | "property2"

var obj: Record<Keys, string> = {
  property: "my first prop",
  property2: "my second prop",
};

आप निश्चित रूप से आगे जा सकते हैं और अपनी संपत्ति के मूल्यों के लिए एक कस्टम प्रकार को परिभाषित कर सकते हैं:

type Keys = "property" | "property2"
type Value = "my prop" | "my other allowed prop"

var obj: Record<Keys, Value> = {
  property: "my prop",
  property2: "my second prop", // TS Error: Type '"my second prop"' is not assignable to type 'Value'.
};

2
बिल्कुल वही जो मुझे चाहिए था। धन्यवाद! जीत के लिए टाइपस्क्रिप्ट!
ऑडिटस

मैं भी यहाँ के letबजाय का उपयोग करेंगे var
Fwd079

3
// Use ..

const Per = {
  name: 'HAMZA',
  age: 20,
  coords: {
    tele: '09',
    lan: '190'
  },
  setAge(age: Number): void {
    this.age = age;
  },
  getAge(): Number {
    return age;
  }
};
const { age, name }: { age: Number; name: String } = Per;
const {
  coords: { tele, lan }
}: { coords: { tele: String; lan: String } } = Per;

console.log(Per.getAge());

3
हे और एसओ में आपका स्वागत है! क्या आप अपने जवाब का विस्तार कर सकते हैं, यह समझाने में मददगार होगा कि यह कैसे / क्यों काम करता है।
पार्टी-रिंग

1

आपके कोड में:

var obj = {
  myProp: string;
};

आप वास्तव में एक ऑब्जेक्ट शाब्दिक बना रहे हैं और संपत्ति myProp को चर स्ट्रिंग असाइन कर रहे हैं। हालांकि यह बहुत बुरा अभ्यास वास्तव में वैध टीएस कोड होगा (इसका उपयोग न करें!):

var string = 'A string';

var obj = {
  property: string
};

हालाँकि, आप जो चाहते हैं वह है कि ऑब्जेक्ट शाब्दिक टाइप किया गया है। इसे विभिन्न तरीकों से प्राप्त किया जा सकता है:

इंटरफेस:

interface myObj {
    property: string;
}

var obj: myObj = { property: "My string" };

कस्टम प्रकार:

type myObjType = {
    property: string
};

var obj: myObjType = { property: "My string" };

कास्ट ऑपरेटर:

var obj = {
    myString: <string> 'hi',
    myNumber: <number> 132,
};

वस्तु प्रकार शाब्दिक:

var obj: { property: string; } = { property: "Mystring" };
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.