声明并初始化打字稿中的字典

给出以下代码

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

为什么不初始化被拒绝? 毕竟,第二个对象没有“lastName”属性。

编辑 :这已经被固定在最新的TS版本。 引用@ Simon_Weaver对OP的post的评论:

注意:这已经被修复了(不确定哪个TS版本)。 我在VS中得到这些错误,就像你所期望的那样: Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'. Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'.


显然这在宣布初始数据时不起作用。 我猜这是TypeScript中的一个错误,所以你应该在项目站点举一个。

你可以通过在声明和初始化中分割你的例子来使用types化的字典,例如:

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

我同意thomaux初始化types检查错误是一个TypeScript错误。 但是,我仍然想find一种方法来在一个语句中声明和初始化一个Dictionary,并进行正确的types检查。 这个实现比较长,但是它增加了一些附加的function,如containsKey(key: string)remove(key: string)方法。 我怀疑这个可以简化0.9版本中的generics可用。

首先我们声明基本的Dictionary类和Interface。 索引器需要该接口,因为类不能实现它们。

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

现在我们声明Person特定的types和Dictionary / Dictionary接口。 在PersonDictionary中注意我们如何覆盖values()toLookup()来返回正确的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; } } 

这里有一个简单的初始化和使用示例:

 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 

在打字稿中使用字典对象,你可以使用如下的接口:

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

并将其用于您的类属性types。

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

如果您想忽略某个属性,请添加一个问号将其标记为可选:

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