【TypeScript】文字列と数値からオブジェクト型リテラルの値を取得する例

前置きは置いておいて先にプログラムの例を以下に示す。

文字列から取り出す例

// enumの代わりにオブジェクトリテラルで変数を定義
const Status = {
    invalid : -1,
    good : 0,
    bad : 1,
} as const;

/** Statusのプロパティの文字列を指定して値を取得する */
function getStatusFromString(statusStr: string): number{
    const status:string[] = Object.keys(Status);
    if(status.includes(statusStr)){
        return Status[statusStr as keyof typeof Status];
    }
    return Status.invalid;
}

// 例
const goodStatus= getStatusFromString("good");
const invalidStatus = getStatusFromString("xxxx");

console.log(`typeof goodStatus: ${typeof goodStatus}. value: ${goodStatus}`);
console.log(`typeof invalidStatus: ${typeof invalidStatus}. value: ${invalidStatus}`);

// typeof goodStatus: number. value: 0
// typeof invalidStatus: number. value: -1

数値から取り出す例

先ほどと同様にStatusについて考える。

const Status = {
    invalid : -1,
    good : 0,
    bad : 1,
} as const;

/** 数値を指定してStatusのプロパティ名を取得する */
function getEnumKeyFromValue(statusNum: number): string{
    const keys: string[] = Object.keys(Status);
    const index = Object.values(Status).indexOf(statusNum);
    if(index !== -1){
        return keys[index];
    }
    return keys[0];
}

// 例
const goodStatus= getEnumKeyFromValue(0);
const invalidStatus = getEnumKeyFromValue(1111);

console.log(`Typeof goodStatus: ${typeof goodStatus}. value: ${goodStatus}`);
console.log(`Typeof invalidStatus: ${typeof invalidStatus}. value: ${invalidStatus}`);
// Typeof goodStatus: string. value: bad
// Typeof invalidStatus: string. value: invalid

何でこの記事を書いたの?

TypeScriptを使っている方なら誰しもが通るであろうTSでの文字列列挙型。

これを扱う際に上記のページでも紹介されているようにユニオン型やオブジェクトリテラルを使うことが多いと思う(実際に自分も仕事ではそうしている)。

このオブジェクト型リテラルのプロパティそのものをUI上に表示する文字列と紐づけたい場合や、Web APIリクエストで取得した数値と紐づけたい場合がある。

そういった例に対応する場合、単純に対応する文字列や数値をswitch文で指定する場合もあると思う。例えば↓のような感じとか。

function getStatusWordFromValue(value: number): string{
  switch (value) {
    case Status.bad:
      return "bad";
    case Status.good:
      return "good";
    default:
      return "invalid"
  }
}

これで問題ない場合もあると思うのだが、今後このStatusのプロパティが増えていったときに保守性が💩 & 💩になることを容易に想像できると思う。単にそれを避けたかった。

おまけ

プログラムの仕様にも依るだろうけど、invalidみたいなステータスを用意するのはチョット不服ではある。

ただ、今回みたいな実装をすると、「基本的には値が決まっているはずだけど、たまに予期しない値が返ってくる」みたいなWeb APIリクエストにも対応できる(というかできてしまう)

例えば/api/cat/memeエンドポイントからは、原則ハッピーハッピーチピチピチャパチャパの文字列しか返ってこないはずだけど(大人の事情で)たまにハァ?が返ってきてしまう、みたいな場合にもプログラム上はエラーを出さずに対応できる。

※TypeScriptのアイコンはここから取得