ウェブサイト検索

typescript2.0 - TypeScriptで文字列配列から型を作成するにはどうすればよいですか?


文字列の配列に基づいて TypeScript の型を作る最良の方法は何ですか?私はバージョン 2.6.2 を使用しています。その配列は長くて、Enum 宣言で文字列の値を繰り返して重複させたくありません。

私がやりたいことは、こんな感じのことです:

const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
export type Color = convertStringArrayToType(colors);

次の解決策(ソース)はうまく動作しますが、ややハッキーに感じます:

/** Utility function to create a K:V from a list of strings */
function strEnum<T extends string>(o: Array<T>): {[K in T]: K} {
  return o.reduce((res, key) => {
    res[key] = key;
    return res;
  }, Object.create(null));
}

/**
  * Sample create a string enum
  */

/** Create a K:V */
const Direction = strEnum([
  'North',
  'South',
  'East',
  'West'
])
/** Create a Type */
type Direction = keyof typeof Direction;

回答 #1

Typescript 3.4以降、as constを使用して、次のように配列からユニオン型を生成することができます

const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'] as const;
export type Color = typeof colors[number]; // 'red'|'orange'|'yellow'|'green'|'blue'|'indigo'|'violet'

回答 #2

@guido-dizioliの回答を基に、動的に型を作成しつつIntelliSenseの恩恵を受けられる再利用可能な関数を作成することができます。

1つ注意点は、呼び出す側が配列をas constで定義する必要があることです:

const properties = [
    "prepare", 
    "loadSession", 
    "proceedBasedOnSession", 
    "fetchConnection"
] as const;

function createObject<T extends readonly string[]>(steps: T): Record<T[number], object> {
    const typed = {} as Record<string, string>;
    steps.forEach(step => typed[step] = step);
    return typed as unknown as Record<T[number], object>;
}

関連記事