Объявление и инициализация словаря в Typescript



учитывая следующий код



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

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


почему инициализация не отклоняется? В конце концов, второй объект не имеет свойства "фамилия".

782   4  

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

    Ничего не найдено.