टाइपस्क्रिप्ट में एक डिक्लेयर को डिक्लेयर और इनिशियलाइज़ करें


248

निम्नलिखित कोड दिया

interface IPerson {
   firstName: string;
   lastName: string;
}

var persons: { [id: string]: IPerson; } = {
   "p1": { firstName: "F1", lastName: "L1" },
   "p2": { firstName: "F2" }
};

आरंभीकरण को अस्वीकार क्यों नहीं किया गया है? आखिरकार, दूसरी वस्तु में "अंतिम नाम" संपत्ति नहीं है।


11
नोट: यह तब से तय किया गया है (निश्चित नहीं कि कौन सा सटीक TS संस्करण है)। मुझे वीएस में ये त्रुटियां मिलती हैं, जैसा कि आप उम्मीद करेंगे: Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'.
सिमोन_विवर

जवाबों:


289

संपादित करें : यह तब से नवीनतम TS संस्करणों में तय किया गया है। ओपी के पोस्ट पर @ Simon_Weaver की टिप्पणी का हवाला देते हुए:

नोट: यह तब से तय हो गया है (निश्चित नहीं कि कौन सा सटीक TS संस्करण है)। मुझे वीएस में ये त्रुटियां मिलीं, जैसा कि आप उम्मीद करेंगे:Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'.


घोषणा में प्रारंभिक डेटा पास करते समय स्पष्ट रूप से यह काम नहीं करता है। मुझे लगता है कि यह टाइपस्क्रिप्ट में एक बग है, इसलिए आपको परियोजना स्थल पर एक उठाना चाहिए।

आप घोषणा और आरंभीकरण में अपने उदाहरण को विभाजित करके टाइप किए गए शब्दकोश का उपयोग कर सकते हैं, जैसे:

var persons: { [id: string] : IPerson; } = {};
persons["p1"] = { firstName: "F1", lastName: "L1" };
persons["p2"] = { firstName: "F2" }; // will result in an error

3
आपको idप्रतीक की आवश्यकता क्यों है ? ऐसा लगता है कि यह अनावश्यक है।
केविक

4
idप्रतीक का उपयोग करके , आप यह घोषित कर सकते हैं कि शब्दकोश की कुंजी किस प्रकार की होनी चाहिए। उपरोक्त घोषणा के साथ, आप निम्न कार्य नहीं कर सकते:persons[1] = { firstName: 'F1', lastName: 'L1' }
thomaux

2
हमेशा किसी न किसी कारण से इस वाक्यविन्यास को भूल जाओ!
eddiewould

12
idप्रतीक की तरह कुछ भी आप नामित किया जा सकता है और यह आसान कोड को पढ़ने के लिए बनाने के लिए इस तरह से डिजाइन किया गया था। जैसे { [username: string] : IPerson; }
गाइ पार्क

1
@Robouste मैं Lodash की findKey विधि का उपयोग करता हूं या यदि आप एक देशी समाधान पसंद करते हैं, तो आप Object.entries पर बना सकते हैं । यदि आप चाबियों की पूरी सूची प्राप्त करने में रुचि रखते हैं, तो Object.keys
thomaux

82

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

interface Dictionary<T> {
    [Key: string]: T;
}

और, अपने वर्ग संपत्ति प्रकार के लिए इसका उपयोग करें।

export class SearchParameters {
    SearchFor: Dictionary<string> = {};
}

इस वर्ग का उपयोग और आरंभ करने के लिए,

getUsers(): Observable<any> {
        var searchParams = new SearchParameters();
        searchParams.SearchFor['userId'] = '1';
        searchParams.SearchFor['userName'] = 'xyz';

        return this.http.post(searchParams, 'users/search')
            .map(res => {
                return res;
            })
            .catch(this.handleError.bind(this));
    }

61

मैं thomaux से सहमत हूँ कि इनिशियलाइज़ेशन टाइप चेकिंग एरर एक टाइपस्क्रिप्ट बग है। हालाँकि, मैं अभी भी एकल स्टेटमेंट में सही प्रकार की जाँच के साथ डिक्लेयर की घोषणा करने और आरंभ करने का एक तरीका खोजना चाहता था। यह कार्यान्वयन लंबा है, हालांकि यह अतिरिक्त कार्यक्षमता जैसे कि ए containsKey(key: string)और remove(key: string)विधि जोड़ता है । मुझे संदेह है कि 0.9 रिलीज में जेनरिक उपलब्ध होने के बाद इसे सरल बनाया जा सकता है।

सबसे पहले हम आधार शब्दकोश वर्ग और इंटरफ़ेस की घोषणा करते हैं। अनुक्रमणिका के लिए इंटरफ़ेस आवश्यक है क्योंकि कक्षाएं उन्हें लागू नहीं कर सकती हैं।

interface IDictionary {
    add(key: string, value: any): void;
    remove(key: string): void;
    containsKey(key: string): bool;
    keys(): string[];
    values(): any[];
}

class Dictionary {

    _keys: string[] = new string[];
    _values: any[] = new any[];

    constructor(init: { key: string; value: any; }[]) {

        for (var x = 0; x < init.length; x++) {
            this[init[x].key] = init[x].value;
            this._keys.push(init[x].key);
            this._values.push(init[x].value);
        }
    }

    add(key: string, value: any) {
        this[key] = value;
        this._keys.push(key);
        this._values.push(value);
    }

    remove(key: string) {
        var index = this._keys.indexOf(key, 0);
        this._keys.splice(index, 1);
        this._values.splice(index, 1);

        delete this[key];
    }

    keys(): string[] {
        return this._keys;
    }

    values(): any[] {
        return this._values;
    }

    containsKey(key: string) {
        if (typeof this[key] === "undefined") {
            return false;
        }

        return true;
    }

    toLookup(): IDictionary {
        return this;
    }
}

अब हम व्यक्ति को विशिष्ट प्रकार और शब्दकोश / शब्दकोश इंटरफ़ेस घोषित करते हैं। पर्सनलाइड में ध्यान दें कि हम कैसे ओवरराइड करते हैं values()और toLookup()सही प्रकार वापस करते हैं।

interface IPerson {
    firstName: string;
    lastName: string;
}

interface IPersonDictionary extends IDictionary {
    [index: string]: IPerson;
    values(): IPerson[];
}

class PersonDictionary extends Dictionary {
    constructor(init: { key: string; value: IPerson; }[]) {
        super(init);
    }

    values(): IPerson[]{
        return this._values;
    }

    toLookup(): IPersonDictionary {
        return this;
    }
}

और यहाँ एक सरल आरंभीकरण और उपयोग उदाहरण है:

var persons = new PersonDictionary([
    { key: "p1", value: { firstName: "F1", lastName: "L2" } },
    { key: "p2", value: { firstName: "F2", lastName: "L2" } },
    { key: "p3", value: { firstName: "F3", lastName: "L3" } }
]).toLookup();


alert(persons["p1"].firstName + " " + persons["p1"].lastName);
// alert: F1 L2

persons.remove("p2");

if (!persons.containsKey("p2")) {
    alert("Key no longer exists");
    // alert: Key no longer exists
}

alert(persons.keys().join(", "));
// alert: p1, p3

बहुत उपयोगी नमूना कोड। "इंटरफ़ेस IDfox" में एक छोटा टाइपो होता है, क्योंकि IPerson का एक संदर्भ होता है।
MGS

तत्व गणना को लागू करने के लिए अच्छा होगा
nurettin

@dmck टाइपस्क्रिप्ट 1.5.0-बीटा केcontainsKey(key: string): bool; साथ घोषणा काम नहीं करती है । इसे बदल दिया जाना चाहिए । containsKey(key: string): boolean;
अमरजीत सिंह

1
क्यों नहीं आप सामान्य प्रकार delcare? डिक्शनरी <टी>, फिर पर्सपेनल क्लास बनाने की कोई जरूरत नहीं है। आप इसे इस तरह घोषित करते हैं: var person = new Dictionary <IPerson> ();
बेनोइट

1
मैंने ऐसे जेनेरिक शब्दकोश का प्रभावी ढंग से उपयोग किया है। मैंने इसे यहाँ पाया: fabiolandoni.ch/…
CAK2

5

यहाँ @dmck से प्रेरित एक अधिक सामान्य शब्दकोश कार्यान्वयन है

    interface IDictionary<T> {
      add(key: string, value: T): void;
      remove(key: string): void;
      containsKey(key: string): boolean;
      keys(): string[];
      values(): T[];
    }

    class Dictionary<T> implements IDictionary<T> {

      _keys: string[] = [];
      _values: T[] = [];

      constructor(init?: { key: string; value: T; }[]) {
        if (init) {
          for (var x = 0; x < init.length; x++) {
            this[init[x].key] = init[x].value;
            this._keys.push(init[x].key);
            this._values.push(init[x].value);
          }
        }
      }

      add(key: string, value: T) {
        this[key] = value;
        this._keys.push(key);
        this._values.push(value);
      }

      remove(key: string) {
        var index = this._keys.indexOf(key, 0);
        this._keys.splice(index, 1);
        this._values.splice(index, 1);

        delete this[key];
      }

      keys(): string[] {
        return this._keys;
      }

      values(): T[] {
        return this._values;
      }

      containsKey(key: string) {
        if (typeof this[key] === "undefined") {
          return false;
        }

        return true;
      }

      toLookup(): IDictionary<T> {
        return this;
      }
    }

3

यदि आप किसी प्रॉपर्टी को अनदेखा करना चाहते हैं, तो प्रश्न चिह्न जोड़कर इसे वैकल्पिक के रूप में चिह्नित करें:

interface IPerson {
    firstName: string;
    lastName?: string;
}

1
प्रश्न का पूरा बिंदु यह है कि दिए गए कोड को अंतिम नाम दिए बिना संकलित क्यों किया गया है ...
पियरे अरलाउड

-1

अब, एक पुस्तकालय है जो टाइपस्क्रिप्ट में दृढ़ता से टाइप किए गए, क्वेरी संग्रह प्रदान करता है ।

ये संग्रह हैं:

  • सूची
  • शब्दकोश

पुस्तकालय को ts-generic-collection-linq कहा जाता है ।

GitHub पर स्रोत कोड:

https://github.com/VeritasSoftware/ts-generic-collections

NPM:

https://www.npmjs.com/package/ts-generic-collections-linq

इस लाइब्रेरी के साथ, आप संग्रह (जैसे List<T>) बना सकते हैं और उन्हें नीचे दिखाए अनुसार क्वेरी कर सकते हैं ।

    let owners = new List<Owner>();

    let owner = new Owner();
    owner.id = 1;
    owner.name = "John Doe";
    owners.add(owner);

    owner = new Owner();
    owner.id = 2;
    owner.name = "Jane Doe";
    owners.add(owner);    

    let pets = new List<Pet>();

    let pet = new Pet();
    pet.ownerId = 2;
    pet.name = "Sam";
    pet.sex = Sex.M;

    pets.add(pet);

    pet = new Pet();
    pet.ownerId = 1;
    pet.name = "Jenny";
    pet.sex = Sex.F;

    pets.add(pet);

    //query to get owners by the sex/gender of their pets
    let ownersByPetSex = owners.join(pets, owner => owner.id, pet => pet.ownerId, (x, y) => new OwnerPet(x,y))
                               .groupBy(x => [x.pet.sex])
                               .select(x =>  new OwnersByPetSex(x.groups[0], x.list.select(x => x.owner)));

    expect(ownersByPetSex.toArray().length === 2).toBeTruthy();

    expect(ownersByPetSex.toArray()[0].sex == Sex.F).toBeTruthy();
    expect(ownersByPetSex.toArray()[0].owners.length === 1).toBeTruthy();
    expect(ownersByPetSex.toArray()[0].owners.toArray()[0].name == "John Doe").toBeTruthy();

    expect(ownersByPetSex.toArray()[1].sex == Sex.M).toBeTruthy();
    expect(ownersByPetSex.toArray()[1].owners.length == 1).toBeTruthy();
    expect(ownersByPetSex.toArray()[1].owners.toArray()[0].name == "Jane Doe").toBeTruthy();

इस के लिए एक NPM पैकेज नहीं मिल सकता है
हैरी

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