336

次のコードを考えると

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

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

初期化が拒否されないのはなぜですか? 結局、2 番目のオブジェクトには「lastName」プロパティがありません。

4

6 に答える 6

387

編集:これは、最新のTSバージョンで修正されています。OPの投稿に対する@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
于 2013-04-08T12:42:39.147 に答える
67

初期化型チェック エラーが TypeScript のバグであるという thomaux に同意します。ただし、正しい型チェックを使用して、1 つのステートメントで Dictionary を宣言して初期化する方法を見つけたいと思っていました。containsKey(key: string)この実装は長くなりますが、remove(key: string)メソッドなどの機能が追加されます。ジェネリックが 0.9 リリースで利用可能になれば、これは単純化できると思います。

最初に、基本 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 固有の型と 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
于 2013-04-08T16:14:38.070 に答える
4

プロパティを無視する場合は、疑問符を追加してオプションとしてマークします。

interface IPerson {
    firstName: string;
    lastName?: string;
}
于 2014-04-09T08:55:22.517 に答える