在Typescript中聲明並初始化一個Dictionary

[英]Declare and initialize a Dictionary in Typescript


Given the following code

給出以下代碼

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

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

Why isn't the initialization rejected? After all, the second object does not have the "lastName" property.

為什么不初始化被拒絕?畢竟,第二個對象沒有“lastName”屬性。

4 个解决方案

#1


179  

Edit: This has since been fixed in the latest TS versions. Quoting @Simon_Weaver's comment on the OP's post:

編輯:此后已在最新的TS版本中修復。引用@ Simon_Weaver對OP帖子的評論:

Note: this has since been fixed (not sure which exact TS version). I get these errors in VS, as you would expect: Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'.

注意:此后已經修復(不確定哪個TS版本)。我在VS中遇到這些錯誤,正如您所期望的那樣:索引簽名不兼容。輸入'{firstName:string; }'不能分配給'IPerson'類型。 'firstName:string;類型'中缺少屬性'lastName'; }”。


Apparently this doesn't work when passing the initial data at declaration. I guess this is a bug in TypeScript, so you should raise one at the project site.

You can make use of the typed dictionary by splitting your example up in declaration and initialization, like:

您可以通過在聲明和初始化中拆分示例來使用類型化字典,例如:

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

#2


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.

我同意thomaux初始化類型檢查錯誤是TypeScript錯誤。但是,我仍然希望找到一種方法,在單個語句中使用正確的類型檢查來聲明和初始化Dictionary。此實現更長,但它添加了其他功能,如containsKey(key:string)和remove(key:string)方法。我懷疑,一旦0.9版本中提供了泛型,這可以簡化。

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

首先,我們聲明基本的Dictionary類和接口。索引器需要該接口,因為類無法實現它們。

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.

現在我們聲明Person特定類型和Dictionary / Dictionary接口。在PersonDictionary中注意我們如何覆蓋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;
    }
}

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

#3


28  

For using dictionary object in typescript you can use interface as below:

要在typescript中使用字典對象,您可以使用如下界面:

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

and, use this for your class property type.

並將其用於您的類屬性類型。

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

to use and initialize this class,

使用和初始化這個類,

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

#4


2  

If you want to ignore a property, mark it as optional by adding a question mark:

如果要忽略屬性,請通過添加問號將其標記為可選:

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

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2013/04/08/724d48c1cf90350c17168ea2f17577ee.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com