web-dev-qa-db-ja.com

タイプスクリプトでインデックスキータイプとしてenumを使用するには?

次の例を検討してください。

enum DialogType {
    Options,
    Help
}

class Dialog { 
    test() : string {
        return "";
    }
}

class Greeter {

    openDialogs: { [key in DialogType]: Dialog | undefined } = {
        0: undefined,
        1: undefined
    };

    getDialog(t: DialogType) {
        return this.openDialogs[t];
    }
}

const greeter = new Greeter();
const d = greeter.getDialog(DialogType.Help);
if (d) document.write(d.test());

遊び場でも

それには3つの問題/質問があります:

  1. プロパティを '|として宣言しているにもかかわらず、初期化リテラルでプロパティを省略できないのはなぜですか未定義'
  2. タイプキーとして「DialogType.Options」を使用できず、代わりにハードコードされた数値を使用する必要があるのはなぜですか?
  3. 「key:DialogType」ではなく「key in DialogType」を使用する必要があるのはなぜですか? (または私はできますか?)
11
ironic
  1. |undefinedはプロパティをオプションにしません。単にundefinedにできることを意味します。|undefinedメンバーをオプションにする提案がありますが、現在は実装されていません。すべてのプロパティをオプションにするには、?の後に]を使用する必要があります

    { [key in DialogType]?: Dialog }
    
  2. ダイアログ列挙値をキーとして使用できますが、計算されたプロパティである必要があります。

    let openDialogs: { [key in DialogType]?: Dialog } = {
        [DialogType.Options]: undefined,
    };
    
  3. { [key: number or string]: Dialog }はインデックス署名です。インデックスシグニチャは、キータイプとしてnumberまたはstringのみに制限されています(この2つの組み合わせでも機能しません)。したがって、インデックスシグネチャを使用する場合は、numberまたはstringでインデックスを作成できます(DialogTypeキーのみに制限することはできません)。ここで使用している概念は、マップされた型と呼ばれます。基本的に、マップされた型は、キーの結合(この場合はDialogType列挙型のメンバー)と一連のマッピングルールに基づいて新しい型を生成します。上記で作成した型は、基本的に次と同等です。

    let o: { [DialogType.Help]?: Dialog; [DialogType.Options]?: Dialog; }