1. ホーム
  2. typescript

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

2023-01-19 09:25:36

質問

次のような例を考えてみましょう。

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. プロパティを '| undefined' と宣言しているにもかかわらず、イニシャライザー リテラルでプロパティを省略できない理由
  2. なぜ 'DialogType.Options' をタイプキーとして使用することができず、代わりにハードコードされた番号を使用しなければならないのでしょうか?
  3. なぜ 'key.DialogType' ではなく 'key in DialogType' を使用しなければならないのでしょうか?DialogType' の代わりに 'DialogType のキー' を使用しなければならないのでしょうか?(または、できますか?)

どのように解決するには?

  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 enum のメンバ)とマッピングルールのセットからなるユニオンに基づいて新しい型を生成します。上で作成した型は、基本的にこれと同等です。

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