मैं टाइपस्क्रिप्ट में किसी ऑब्जेक्ट को गतिशील रूप से कैसे असाइन करूं?


359

अगर मैं जावास्क्रिप्ट में किसी ऑब्जेक्ट को किसी प्रोग्राम को असाइन करना चाहता हूं, तो मैं इसे इस तरह से करूंगा:

var obj = {};
obj.prop = "value";

लेकिन टाइपस्क्रिप्ट में, यह एक त्रुटि उत्पन्न करता है:

प्रॉपर्टी 'प्रोप' टाइप '{}' के मान पर मौजूद नहीं है

मुझे टाइपस्क्रिप्ट में किसी भी नई संपत्ति को कैसे निर्दिष्ट करना चाहिए?


1
FYI करें। यदि आप इसका अनुसरण करना चाहते हैं तो मैंने इससे संबंधित एक चर्चा खोली है।
— joshuapoehls

जवाबों:


454

के objरूप में निरूपित करना संभव है any, लेकिन यह टाइपस्क्रिप्ट का उपयोग करने के पूरे उद्देश्य को हरा देता है। obj = {}तात्पर्य objहै a Object। इसे चिह्नित करने anyसे कोई मतलब नहीं है। वांछित स्थिरता को पूरा करने के लिए एक इंटरफ़ेस निम्नानुसार परिभाषित किया जा सकता है।

interface LooseObject {
    [key: string]: any
}

var obj: LooseObject = {};

या इसे कॉम्पैक्ट बनाने के लिए:

var obj: {[k: string]: any} = {};

LooseObjectकिसी भी स्ट्रिंग के साथ फ़ील्ड को कुंजी के रूप में स्वीकार कर सकते हैं और anyमान के रूप में टाइप कर सकते हैं ।

obj.prop = "value";
obj.prop2 = 88;

इस समाधान की वास्तविक लालित्य यह है कि आप इंटरफ़ेस में टाइपसेफ़ फ़ील्ड शामिल कर सकते हैं।

interface MyType {
    typesafeProp1?: number,
    requiredProp1: string,
    [key: string]: any
}

var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number

obj.prop = "value";
obj.prop2 = 88;

हालांकि यह मूल प्रश्न का उत्तर देता है , @GreeneCreations द्वारा यहां दिए गए उत्तर समस्या का दृष्टिकोण करने के तरीके पर एक और दृष्टिकोण दे सकते हैं।


13
मुझे लगता है कि यह अब सबसे अच्छा समाधान है। मुझे लगता है कि जिस समय यह प्रश्न अनुक्रमणिका गुणों से पूछा गया था, वह टाइपस्क्रिप्ट में अभी तक लागू नहीं किया गया था।
— पीटर ओल्सन

कैसे के बारे में त्रुटि की तरह मूल वस्तु
— Wayou

@ त्रुटि और सरणी जैसी मूल वस्तुएँ ऑब्जेक्ट से विरासत में मिली हैं। तो LooseObjectएक एरर भी ले सकते हैं।
— आकाश कुरियन जोस

क्या आप जांच सकते हैं कि वस्तु में एक निश्चित (गतिशील) संपत्ति है?
— phhbr

1
इन ढीली वस्तुओं के लिए, आप उन्हें गेट्टर-सेटर के रूप में कैसे लिखते हैं?
— जोकबैटमैन

81

या सभी एक बार में:

  var obj:any = {}
  obj.prop = 5;

41
टाइपस्क्रिप्ट का क्या मतलब है अगर मुझे anyइसे इस्तेमाल करने के लिए बहुत सी चीजें डालनी हैं ? बस मेरे कोड में अतिरिक्त शोर हो जाता है ..: /
— अजाक्सलेयंग

16
@AjaxLeung यदि आपको ऐसा करने की आवश्यकता है, तो आप इसका गलत उपयोग कर रहे हैं।
— एलेक्स

2
ऊपर दिया गया अतिरिक्त संपादन देखें जो ऑब्जेक्ट को पिछले प्रकार को संरक्षित करता है।
— आंद्रे वियाना

6
@AjaxLeung आपको बहुत कम ही कास्ट करना चाहिए any। टाइपस्क्रिप्ट का उपयोग संकलन समय पर (संभावित) त्रुटियों को पकड़ने के लिए किया जाता है। यदि आप anyत्रुटियों को म्यूट करना चाहते हैं तो आप टाइपिंग की शक्ति खो देते हैं और शुद्ध जेएस पर वापस जा सकते हैं। anyआदर्श रूप से केवल तब उपयोग किया जाना चाहिए जब आप उस कोड का आयात कर रहे हों जिसके लिए आप TS परिभाषाएँ नहीं लिख सकते हैं या अपने कोड को JS से TS में माइग्रेट कर रहे हैं
— Precastic

63

मैं anyदूसरी तरफ रखना चाहता हूँ, var foo:IFoo = <any>{};इसलिए कुछ ऐसा है जो अभी भी प्रकार है:

interface IFoo{
    bar:string;
    baz:string;
    boo:string;     
}

// How I tend to intialize 
var foo:IFoo = <any>{};

foo.bar = "asdf";
foo.baz = "boo";
foo.boo = "boo";

// the following is an error, 
// so you haven't lost type safety
foo.bar = 123; 

वैकल्पिक रूप से आप इन गुणों को वैकल्पिक के रूप में चिह्नित कर सकते हैं:

interface IFoo{
    bar?:string;
    baz?:string;
    boo?:string;    
}

// Now your simple initialization works
var foo:IFoo = {};

इसे ऑनलाइन आज़माएं


5
+1 एकमात्र समाधान है जो टाइप सुरक्षा रखता है। बस सुनिश्चित करें कि आप इसके बाद सीधे सभी गैर-वैकल्पिक गुणों को इंस्टेंसेट करें, ताकि बाद में आपको काटने वाले कीड़े से बचा जा सके।
— ऐदीकापी

क्या यह वास्तव में काम करता है? संकलन के बाद भी मेरी जावास्क्रिप्ट में <a> {} है।
— bvs

4
I still have <any>{तो आप संकलित नहीं किया है। टाइपस्क्रिप्ट इसे अपने उत्सर्जन में
— बेसरात

4
इन दिनों var foo: IFoo = {} as anyपसंद किया जाता है। टाइपकास्टिंग के लिए पुराना सिंटैक्स TSX (टाइपस्क्रिप्ट-इफिस JSX) से टकरा रहा था।
— डॉन

51

यह समाधान तब उपयोगी होता है जब आपकी वस्तु में विशिष्ट प्रकार होता है। जैसे कि अन्य स्रोत पर वस्तु प्राप्त करते समय।

let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.

7
यह एकबारगी असाइनमेंट के लिए सही समाधान है।
— sound_typed

इस जवाब ने मेरे लिए काम किया क्योंकि फेसबुक लॉगिन के लिए मुझे विंडो ऑब्जेक्ट में गुण जोड़ना पड़ा । टाइपस्क्रिप्ट में कीवर्ड के रूप में मेरा पहला प्रयोग ।
— एलनऑब्जेक्ट

33

यद्यपि संकलक शिकायत करता है कि इसे अभी भी इसे आउटपुट करना चाहिए जैसा कि आपको आवश्यक है। हालांकि, यह काम करेगा।

var s = {};
s['prop'] = true;

2
हाँ ठीक है, यह वास्तव में स्क्रिप्ट का प्रकार नहीं है, आप अंतर्मुखी हैं।
— pregmatch

25

एक और विकल्प यह है कि संपत्ति को एक संग्रह के रूप में एक्सेस करना है:

var obj = {};
obj['prop'] = "value";


2
यह सबसे संक्षिप्त तरीका है। Object.assign(obj, {prop: "value"})ES6 / ES2015 से भी काम करता है।
— चार्ल्स

8

मुझे आश्चर्य है कि जब भी मैं जावास्क्रिप्ट में "संरचना" के बारे में सोचता हूं, तो कोई भी उत्तर संदर्भ Object.assign का उपयोग नहीं करता है।

और यह टाइपस्क्रिप्ट में अपेक्षित रूप से काम करता है:

interface IExisting {
    userName: string
}

interface INewStuff {
    email: string
}

const existingObject: IExisting = {
    userName: "jsmith"
}

const objectWithAllProps: IExisting & INewStuff = Object.assign({}, existingObject, {
    email: "jsmith@someplace.com"
})

console.log(objectWithAllProps.email); // jsmith@someplace.com

लाभ

  • टाइप सुरक्षा के लिए क्योंकि आपको anyटाइप का उपयोग करने की आवश्यकता नहीं है
  • टाइपस्क्रिप्ट के कुल प्रकार का उपयोग करता है (जैसा &कि घोषणा करते समय टाइप किया जाता है objectWithAllProps), जो स्पष्ट रूप से संचार करता है कि हम एक नए प्रकार की रचना कर रहे हैं (यानी गतिशील रूप से)

के बारे में पता करने के लिए चीजें

  1. Object.assign के अपने अनूठे पहलू हैं (जो कि सबसे अनुभवी जेएस देवों से अच्छी तरह से परिचित हैं) जिन्हें टाइपस्क्रिप्ट लिखते समय विचार किया जाना चाहिए।
    • यह एक उत्परिवर्ती फैशन, या एक अपरिवर्तनीय तरीके से इस्तेमाल किया जा सकता है (मैं ऊपर के अपरिवर्तनीय तरीके को प्रदर्शित करता हूं, जिसका अर्थ है कि existingObjectअछूता रहता है और इसलिए emailसंपत्ति नहीं है । अधिकांश कार्यात्मक-शैली प्रोग्रामर के लिए, परिणाम के बाद से यह एक अच्छी बात है। केवल नया परिवर्तन)।
    • Object.assign सबसे अच्छा काम करता है जब आपके पास चापलूसी की चीजें होती हैं। यदि आप दो नेस्टेड ऑब्जेक्ट्स को मिला रहे हैं, जिनमें अशक्त गुण हैं, तो आप अपरिभाषित के साथ सत्य मानों को अधिलेखित कर सकते हैं। यदि आप Object.assign तर्कों के क्रम के लिए बाहर देखते हैं, तो आपको ठीक होना चाहिए।

मेरे लिए, ऐसे उदाहरणों में जहां आपको डेटा को प्रदर्शित करने के लिए इसका उपयोग करने की आवश्यकता है, यह ठीक काम करता है, लेकिन जब आपको संशोधित प्रकारों की प्रविष्टियों को किसी सरणी में जोड़ना होगा, तो यह बहुत अच्छा काम नहीं करता है। मैंने ऑब्जेक्ट को गतिशील रूप से रचना करने और इसे एक पंक्ति में असाइन करने का सहारा लिया, फिर क्रमिक लाइनों में गतिशील गुणों को असाइन किया। यह मुझे वहां सबसे ज्यादा मिला, इसलिए धन्यवाद।
— शफीक जेठा

8

आप प्रसार ऑपरेटर का उपयोग करके पुरानी वस्तु के आधार पर नई वस्तु बना सकते हैं

interface MyObject {
    prop1: string;
}

const myObj: MyObject = {
    prop1: 'foo',
}

const newObj = {
    ...myObj,
    prop2: 'bar',
}

console.log(newObj.prop2); // 'bar'

टाइपस्क्रिप्ट मूल वस्तु के सभी क्षेत्रों का अनुमान लगाएगा और VSCode स्वतः पूर्णता, आदि करेगा।


अच्छा है, लेकिन अगर आपको pro2 का उपयोग करने की आवश्यकता है जैसे prop3, तो लागू करना कठिन होगा
— ya_dimon


5

किसी मौजूदा ऑब्जेक्ट से किसी सदस्य को जोड़ना संभव है

  1. प्रकार को चौड़ा करना (पढ़ें: इंटरफ़ेस का विस्तार / विशेषज्ञ करें)
  2. मूल ऑब्जेक्ट को विस्तारित प्रकार पर कास्ट करें
  3. सदस्य को ऑब्जेक्ट में जोड़ें
interface IEnhancedPromise<T> extends Promise<T> {
    sayHello(): void;
}

const p = Promise.resolve("Peter");

const enhancedPromise = p as IEnhancedPromise<string>;

enhancedPromise.sayHello = () => enhancedPromise.then(value => console.info("Hello " + value));

// eventually prints "Hello Peter"
enhancedPromise.sayHello();

1
मेरे लिए सबसे अच्छा समाधान। मैंने आज कुछ नया सीखा है, धन्यवाद
— मौरिस

मुझे इस कोड के साथ TS2352 त्रुटि मिलती है
— ya_dimon

@ya_dimon ने इसे टाइपस्क्रिप्ट प्लेग्राउंड पर आज़माया: typecriptlang.org/play यह ठीक काम करता है!
— डैनियल डिट्रिच

@DanielDietrich अब काम करता है .. thx, पता नहीं क्या हुआ।
— ya_dimon

आपका स्वागत है! बदलाव होता है;)
— डैनियल डायट्रिच

5

चूंकि आप ऐसा नहीं कर सकते:

obj.prop = 'value';

यदि आपका टीएस कंपाइलर और आपका लिंटर आपको सख्त नहीं करता है, तो आप इसे लिख सकते हैं:

obj['prop'] = 'value';

यदि आपका टीएस कंपाइलर या लाइनर सख्त है, तो दूसरा जवाब टाइपकास्ट करना होगा:

var obj = {};
obj = obj as unknown as { prop: string };
obj.prop = "value";

3
यह है अगर tsconfig.json पर 'noImplicitAny: false'
— LEMUEL ADANE

इसके अलावा आप GreeneCreations का जवाब दे सकते हैं।
— LEMUEL ADANE

4

किसी भी प्रकार की वस्तु पर किसी भी नई संपत्ति को 'टाइप' करके टाइप करें:

var extend = <any>myObject;
extend.NewProperty = anotherObject;

बाद में आप इसे अपनी विस्तारित वस्तु को 'किसी' पर वापस डालकर पुनः प्राप्त कर सकते हैं:

var extendedObject = <any>myObject;
var anotherObject = <AnotherObjectType>extendedObject.NewProperty;

यह पूरी तरह से सही समाधान है। मान लें कि आपके पास एक ऑब्जेक्ट है o: ObjectType; .... बाद में आप ओ को किसी भी (<any> o) .newProperty = 'foo' में डाल सकते हैं; और इसे पुनः प्राप्त किया जा सकता है (<any> o) .newProperty। कोई संकलक त्रुटियां नहीं है और एक आकर्षण की तरह काम करता है।
— मैट एशले

इस ब्रेक intellisense ... वहाँ यह करने के लिए, लेकिन intellisense रखने के लिए कोई रास्ता नहीं है?
— pregmatch

4

यह गारंटी देने के लिए कि प्रकार एक Object(यानी की-वैल्यू पेयर ) है, उपयोग करें:

const obj: {[x: string]: any} = {}
obj.prop = 'cool beans'

4
  • मामला एक:

    var car = {type: "BMW", model: "i8", color: "white"}; car['owner'] = "ibrahim"; // You can add a property:

  • केस 2:

    var car:any = {type: "BMW", model: "i8", color: "white"}; car.owner = "ibrahim"; // You can set a property: use any type


4

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

this.model = Object.assign(this.model, { newProp: 0 });

3

चेतावनियों को चुप कराने के लिए आप इस घोषणा को जोड़ सकते हैं।

declare var obj: any;



3

अपने पिछले प्रकार को संरक्षित करने के लिए, अस्थायी रूप से अपनी वस्तु को किसी पर भी डालें

  var obj = {}
  (<any>obj).prop = 5;

नई गतिशील संपत्ति केवल तभी उपलब्ध होगी जब आप कलाकारों का उपयोग करेंगे:

  var a = obj.prop; ==> Will generate a compiler error
  var b = (<any>obj).prop; ==> Will assign 5 to b with no error;

3

यहाँ का एक विशेष संस्करण है Object.assign, जो हर संपत्ति परिवर्तन के साथ चर प्रकार को स्वचालित रूप से समायोजित करता है। अतिरिक्त चर, प्रकार अभिकथन, स्पष्ट प्रकार या वस्तु प्रतियों की कोई आवश्यकता नहीं:

function assign<T, U>(target: T, source: U): asserts target is T & U {
    Object.assign(target, source)
}

const obj = {};
assign(obj, { prop1: "foo" })
//  const obj now has type { prop1: string; }
obj.prop1 // string
assign(obj, { prop2: 42 })
//  const obj now has type { prop1: string; prop2: number; }
obj.prop2 // number

//  const obj: { prop1: "foo", prop2: 42 }

नोट: नमूना TS 3.7 अभिकथन कार्यों का उपयोग करता है । की वापसी प्रकार assignहै voidके विपरीत, Object.assign।


1

यदि आप टाइपस्क्रिप्ट का उपयोग कर रहे हैं, तो संभवतः आप प्रकार की सुरक्षा का उपयोग करना चाहते हैं; जिस स्थिति में नग्न वस्तु और 'किसी' का प्रतिकार किया जाता है।

ऑब्जेक्ट या {} का उपयोग न करने के लिए बेहतर है, लेकिन कुछ नामित प्रकार; या आप विशिष्ट प्रकार के साथ एक एपीआई का उपयोग कर सकते हैं, जिसे आपको अपने स्वयं के क्षेत्रों के साथ विस्तारित करने की आवश्यकता है। मैंने इसे काम करने के लिए पाया है:

class Given { ... }  // API specified fields; or maybe it's just Object {}

interface PropAble extends Given {
    props?: string;  // you can cast any Given to this and set .props
    // '?' indicates that the field is optional
}
let g:Given = getTheGivenObject();
(g as PropAble).props = "value for my new field";

// to avoid constantly casting: 
let k:PropAble = getTheGivenObject();
k.props = "value for props";

1

टाइपस्क्रिप्ट में किसी ऑब्जेक्ट को गतिशील रूप से असाइन करें।

ऐसा करने के लिए आपको बस टाइपस्क्रिप्ट इंटरफेस का उपयोग करने की आवश्यकता है:

interface IValue {
    prop1: string;
    prop2: string;
}

interface IType {
    [code: string]: IValue;
}

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

var obj: IType = {};
obj['code1'] = { 
    prop1: 'prop 1 value', 
    prop2: 'prop 2 value' 
};

1
मैं आपके कोड के साथ कोशिश करता हूं, लेकिन मुझे कोई त्रुटि नहीं मिलती है: pastebin.com/NBvJifzN
— pablorsk

1
attributesअंदर फ़ील्ड को इनिशियलाइज़ करने की कोशिश करें SomeClass और जो इसे ठीक करना चाहिए public attributes: IType = {}; pastebin.com/3xnu0TnN
— Nerdroid

1

इसे इस्तेमाल करे:

export interface QueryParams {
    page?: number,
    limit?: number,
    name?: string,
    sort?: string,
    direction?: string
}

फिर इसका उपयोग करें

const query = {
    name: 'abc'
}
query.page = 1

0

एकमात्र समाधान जो पूरी तरह से सुरक्षित है यह एक है , लेकिन थोड़ी सी चिंता है और आपको कई ऑब्जेक्ट बनाने के लिए मजबूर करती है।

आप तो चाहिए पहले एक खाली वस्तु बनाने, तो इन दो समाधान में से एक चुनें। ध्यान रखें कि हर बार जब आप उपयोग करते हैं as, तो आप सुरक्षा खो रहे हैं।

सुरक्षित समाधान

के प्रकार objectहै सुरक्षित अंदर getObjectहै, जो साधन object.aप्रकार का हो जाएगाstring | undefined

interface Example {
  a: string;
  b: number;
}

function getObject() {
  const object: Partial<Example> = {};
  object.a = 'one';
  object.b = 1;
  return object as Example;
}

संक्षिप्त समाधान

के प्रकार objectहै सुरक्षित नहीं अंदर getObjectहै, जो साधन object.aप्रकार के हो जाएगा stringयहां तक कि अपने काम से पहले।

interface Example {
  a: string;
  b: number;
}

function getObject() {
  const object = {} as Example;
  object.a = 'one';
  object.b = 1;
  return object;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.