ウェブサイト検索

typescript - Enumに関数を追加する


TypeScriptでEnum型に関数を追加することは可能ですか?

例えば:

enum Mode {
    landscape,
    portrait,

    // the dream...
    toString() { console.log(this); } 
}

または:

class ModeExtension {
    public toString = () => console.log(this);
}

enum Mode extends ModeExtension {
    landscape,
    portrait,
}

もちろん、toString() 関数には switch のようなものが含まれるでしょう。しかし、ユースケースは次のような流れになります:

class Device {
    constructor(public mode:Mode) {
        console.log(this.mode.toString());
    }
}

enumを拡張することが奇妙に思える理由は理解していますが、可能かどうか気になっています。

回答 #1

Enumとは別のクラスを持ち、それを使って欲しいものを取得することもできますし、名前空間をEnumに統合して、見た目上同じ場所でそれらすべてを取得することもできます。

モードユーティリティクラス

これは正確にあなたが求めているものではありませんが、これにより静的メソッドを使って「モードを文字列に変換する」動作をカプセル化することができます。

class ModeUtil {
    public static toString(mode: Mode) {
        return Mode[mode];
    }
}

このように使うことができます:

const mode = Mode.portrait;
const x = ModeUtil.toString(mode);
console.log(x);

モード列挙型/名前空間の結合

追加のメソッドを持つEnumのように見えるものを作成するために、名前空間をEnumと結合することができます:

enum Mode {
    X,
    Y
}

namespace Mode {
    export function toString(mode: Mode): string {
        return Mode[mode];
    }

    export function parse(mode: string): Mode {
        return Mode[mode];
    }
}

const mode = Mode.X;

const str = Mode.toString(mode);
alert(str);

const m = Mode.parse(str);
alert(m);

回答 #2

非定数列挙型の文字列値は、角かっこを使用して取得できます:

class Device {
    constructor(public mode:Mode) {
        console.log(Mode[this.mode]);
    }
}

enum固有のユーティリティ関数をenumに入れることもできますが、それは単に静的クラスメンバーと同じです:

enum Mode {
    landscape,
    portrait
}

namespace Mode {
    export function doSomething(mode:Mode) {
        // your code here
    }
}

回答 #3

enum を列挙型パターンに変換してください。これは多くの言語において一般的により良い方法だと思います。なぜなら、そうしないと型のカプセル化のオプションが制限されてしまうからです。列挙型の値に基づいて switch する傾向がありますが、本来は特定の列挙型の値に依存するデータや機能は、各列挙項目のインスタンス自体に含めるべきです。いくつかのコードも追加してデモンストレーションしています。

基になる列挙型の値に特に依存している場合、これはうまくいかないかもしれません。その場合は、古い値のためのメンバーを追加し、必要な箇所を新しいプロパティを使うように変換する必要があります。

class Mode {
   public static landscape = new Mode(1920, 1080);
   public static portrait = new Mode(1080, 1920);

   public get Width(): number { return this.mWidth; }
   public get Height(): number { return this.mHeight; }

   // private constructor if possible in a future version of TS
   constructor(
      private mWidth: number,
      private mHeight: number
   ) {
   }

   public GetAspectRatio() {
      return this.mWidth / this.mHeight;
   }
}

回答 #4

フェントン溶液への追加です。この列挙型を別のクラスで使用したい場合は、列挙型と名前空間の両方をエクスポートする必要があります。見た目は次のようになります:

export enum Mode {
    landscape,
    portrait
}

export namespace Mode {
    export function toString(mode: Mode): string {
        return Mode[mode];
    }
}

それから、あなたのクラスに mode.enum.ts ファイルをインポートして、それを使用します。

関連記事