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