声明并初始化打字稿中的字典
给出以下代码
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; }