web-dev-qa-db-ja.com

typescriptのカスタムリテラル型を反復する方法

TypeScriptでカスタムリテラルタイプを定義しました。

export type Market = 'au'|'br'|'de';

ここで、最初にMarket[]の配列を作成する必要なく、可能な各Marketを反復処理したいと思いますfeels冗長であり、オプションを1つ追加するのを忘れる可能性があります。

const markets: Market[] = ['au', 'br', 'de'];
markets.forEach((market: Market) => {
    console.log(market);
});

Typescriptでそれを達成する方法はありますか?

18
k0pernikus

いいえ、そのような純粋な型情報は実行時に存在しないため、それを行うことはできません。

逆の方法をとるのは仮説上もっともらしいことです(通常の文字列のリストを定義してから、'au'|'br'|'de' type from that)ですが、TypeScriptコンパイラ(2.0または2.1)が現時点でそれを推測することはないと思います-私が知る限り、市場のタイプは常にstring[] 通常は。

これに対する正しい答えは、列挙型を使用することです。それらはそれぞれの値でタイプを定義し、それらすべての文字列値のリストを取得することが可能です: TypeScript 0.9.5で列挙型をプログラムで列挙する方法

列挙型の欠点の1つは、ランタイムの表現が異なることです(内部では、文字列ではなく実際には数値です)。あなたのコードはそれらをニース可読値として扱うことができますが、実行時にそれらを文字列名として必要とする場合、それらを文字列に変換する必要があるだけです。それは簡単ですが、列挙型MarketEnumと値myEnumValueMarketEnum[myEnumValue]は、文字列としての値の名前です)。

8
Tim Perry

ここに別の方法があります:

enum Market {
   'eu' = 'eu',
   'us' = 'us',
}

const all_possible_market_values = getStringValuesFromEnum(Market)

function getStringValuesFromEnum<T>(myEnum: T): (keyof T)[] {
   return Object.keys(myEnum) as any
}

基礎となる表現は、もはや文字列である番号ではありません。

"use strict";
var Market;

(function (Market) {
    Market["eu"] = "eu";
    Market["us"] = "us";
})(Market || (Market = {}));

const all_possible_market_values = getStringValuesFromEnum(Market);

function getStringValuesFromEnum(myEnum) {
    return Object.keys(myEnum);
}
1

実行時にすべての値を含み、コンパイル時にチェックされる配列を作成するために私が行うことは次のとおりです。

export type Market = 'eu' | 'us'

export const MARKET_TYPES: Market[] = (() => {
   const markets: Market[] = ['eu', 'us']

   return markets.map((x: Market) => {
      if (x === 'eu') {
         return x
      } else if (x === 'us') {
         return x
      } else {
         const _exhaustive_check: never = x
         return _exhaustive_check
      }
   })
})()
1