web-dev-qa-db-ja.com

TypeScript配列から文字列リテラル型

現在、文字列の配列と同じ文字列を含む文字列リテラルの共用体型があります。

const furniture = ['chair', 'table', 'lamp'];
type Furniture = 'chair' | 'table' | 'lamp';

私は自分のアプリケーションで両方が必要ですが、コードを乾燥させておきたいと思っています。それで、一方を他方から推測する方法はありますか?

基本的にはtype Furniture = [any string in furniture array]なので、重複する文字列はありません。

41
Duncan Luk

TypeScript 3.0の更新:

一般的な残りのパラメーターを使用すると、string[]をリテラルのタプル型として正しく推測し、リテラルの共用体型を取得する方法があります。

こんなふうになります:

const Tuple = <T extends string[]>(...args: T) => args;
const furniture = Tuple('chair', 'table', 'lamp');
type Furniture = typeof furniture[number];

一般的なレストパラメータの詳細

TypeScript 3.4の更新:

TypeScriptバージョン3.4では、いわゆるconst contextsが導入されています。これは、タプル型を不変として宣言し、狭いリテラル型を直接取得する方法です(上記のような関数を呼び出す必要があります)。

この新しい構文により、次のニース簡潔なソリューションが得られます。

const furniture = ['chair', 'table', 'lamp'] as const;
type Furniture = typeof furniture[number];

新しいconstコンテキストの詳細はこのPRにあります および リリースノート にもあります。

73
ggradnig

この回答は古くなっています。上記の回答を参照してください。

利用可能な最善の回避策:

const furnitureObj = { chair: 1, table: 1, lamp: 1 };
type Furniture = keyof typeof furnitureObj;
const furniture = Object.keys(furnitureObj) as Furniture[];

理想的にはこれを行うことができます:

const furniture = ['chair', 'table', 'lamp'];
type Furniture = typeof furniture[number];

残念ながら、今日のfurniturestring[]と推定されます。つまり、Furniturestringになりました。

手動アノテーションを使用してリテラルとして型付けを強制できますが、重複が返されます。

const furniture = ["chair", "table", "lamp"] as ["chair", "table", "lamp"];
type Furniture = typeof furniture[number];

TypeScript issue#10195 は、リストがstring[]ではなく静的タプルとして推論される必要があることをTypeScriptに示唆する機能を追跡するため、将来的には可能になるでしょう。

10
Denis