Declare and initialize a Dictionary in Typescript

前端 未结 6 1071
闹比i
闹比i 2020-12-02 04:22

Given the following code

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

var persons: { [id: string]: IPerson; } = {
   \"p1\": { firstName         


        
6条回答
  •  没有蜡笔的小新
    2020-12-02 04:46

    I agree with thomaux that the initialization type checking error is a TypeScript bug. However, I still wanted to find a way to declare and initialize a Dictionary in a single statement with correct type checking. This implementation is longer, however it adds additional functionality such as a containsKey(key: string) and remove(key: string) method. I suspect that this could be simplified once generics are available in the 0.9 release.

    First we declare the base Dictionary class and Interface. The interface is required for the indexer because classes cannot implement them.

    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;
        }
    }
    

    Now we declare the Person specific type and Dictionary/Dictionary interface. In the PersonDictionary note how we override values() and toLookup() to return the correct types.

    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;
        }
    }
    

    And here is a simple initialization and usage example:

    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
    

提交回复
热议问题