dictionary initialization typescript

typescript iterate dictionary



Declarar e inicializar un diccionario en Typescript (4)

Estoy de acuerdo con thomaux en que el error de comprobación de tipo de inicialización es un error de TypeScript. Sin embargo, todavía quería encontrar una forma de declarar e inicializar un diccionario en una sola declaración con la verificación de tipos correcta. Esta implementación es más larga, sin embargo, agrega funcionalidad adicional, como un método containsKey(key: string) y remove(key: string) . Sospecho que esto podría simplificarse una vez que los genéricos estén disponibles en la versión 0.9.

Primero declaramos la clase de diccionario base y la interfaz. La interfaz es necesaria para el indexador porque las clases no pueden implementarlas.

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

Ahora declaramos el tipo específico de Persona y la interfaz Diccionario / Diccionario. En la nota de PersonDictionary, anulamos los values() y toLookup() para devolver los tipos correctos.

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

Y aquí hay un ejemplo simple de inicialización y uso:

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

Dado el siguiente código

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

¿Por qué no se rechaza la inicialización? Después de todo, el segundo objeto no tiene la propiedad "lastName".


Para usar el objeto de diccionario en mecanografiado, puede usar la interfaz de la siguiente manera:

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

y, use esto para su tipo de propiedad de clase.

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

para usar e inicializar esta clase,

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


Si desea ignorar una propiedad, márquela como opcional agregando un signo de interrogación:

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


Editar : Esto se ha solucionado en las últimas versiones TS. Citando el comentario de @ Simon_Weaver en la publicación de OP:

Nota: esto se ha corregido desde entonces (no estoy seguro de qué versión exacta de TS). Obtengo estos errores en VS, como era de esperar: las 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; }''.

Aparentemente, esto no funciona al pasar los datos iniciales en la declaración. Supongo que esto es un error en TypeScript, por lo que debe crear uno en el sitio del proyecto.

Puede utilizar el diccionario tipeado dividiendo su ejemplo en declaración e inicialización, como:

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