Объявление и инициализация словаря в Typescript
учитывая следующий код
interface IPerson {
firstName: string;
lastName: string;
}
var persons: { [id: string]: IPerson; } = {
"p1": { firstName: "F1", lastName: "L1" },
"p2": { firstName: "F2" }
};
почему инициализация не отклоняется? В конце концов, второй объект не имеет свойства "фамилия".
4 ответов:
Edit: С тех пор это было исправлено в последних версиях TS. Цитируя комментарий @Simon_Weaver на пост ОП:
Примечание: с тех пор это было исправлено (не уверен, какая именно версия TS). Я получите эти ошибки в VS, как и следовало ожидать:
Index signatures are incompatible. Type '{ firstName: string; }' is not assignable to type 'IPerson'. Property 'lastName' is missing in type '{ firstName: string; }'.
По-видимому, это не работает при передаче исходных данных при объявлении. Я думаю, это ошибка в TypeScript, поэтому вы должны поднять один в проекте сайт.вы можете использовать типизированный словарь, разделив свой пример на объявление и инициализацию, например:
var persons: { [id: string] : IPerson; } = {}; persons["p1"] = { firstName: "F1", lastName: "L1" }; persons["p2"] = { firstName: "F2" }; // will result in an error
Я согласен с thomaux, что ошибка проверки типа инициализации является ошибкой TypeScript. Тем не менее, я все еще хотел найти способ объявить и инициализировать словарь в одном операторе с правильной проверкой типа. Эта реализация длиннее, однако она добавляет дополнительные функции, такие как
containsKey(key: string)иremove(key: string)метод. Я подозреваю, что это может быть упрощено, как только дженерики будут доступны в версии 0.9.Сначала мы объявляем базовый класс словаря и интерфейс. Интерфейс необходим для индексатора, поскольку классы не могут их реализовать.
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; } }теперь мы объявляем конкретный тип человека и словарь / словарь интерфейса. В 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; } }а вот простой пример инициализации и использования:
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
для использования объекта словаря в typescript вы можете использовать интерфейс, как показано ниже:
interface Dictionary<T> { [Key: string]: T; }и использовать это для вашего типа класса.
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; }
Comments