web-dev-qa-db-fra.com

Tableau TypeScript en type littéral chaîne

J'ai actuellement à la fois un tableau de chaînes et un type d'union littéral de chaîne contenant les mêmes chaînes:

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

J'ai besoin des deux dans ma candidature, mais j'essaie de garder mon code SEC. Existe-t-il un moyen de déduire l'un de l'autre?

Je veux essentiellement dire quelque chose comme type Furniture = [any string in furniture array], il n'y a donc pas de chaînes en double.

41
Duncan Luk

Mise à jour pour TypeScript 3.0:

Avec l'utilisation de paramètres de repos génériques, il existe un moyen de déduire correctement string[] comme type de Tuple littéral, puis obtenez le type d'union des littéraux.

Ça va comme ça:

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

En savoir plus sur les paramètres de repos génériques

Mise à jour pour TypeScript 3.4:

TypeScript version 3.4 a introduit les soi-disant contextes const , qui sont un moyen de déclarer un type Tuple immuable et d'obtenir directement le type littéral étroit (sans le besoin d'appeler une fonction comme indiqué ci-dessus).

Avec cette nouvelle syntaxe, nous obtenons cette belle solution concise:

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

Plus d'informations sur les nouveaux contextes const se trouvent dans ce PR ainsi que dans les notes de version .

73
ggradnig

Cette réponse est obsolète, voir la réponse ci-dessus.

La meilleure solution de contournement disponible:

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

Idéalement, nous pourrions le faire:

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

Malheureusement, aujourd'hui furniture est déduit comme string[], ce qui signifie que Furniture est désormais également un string.

Nous pouvons appliquer le typage comme un littéral avec une annotation manuelle, mais cela ramène la duplication:

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

TypeScript problème # 10195 suit la possibilité d'indiquer à TypeScript que la liste doit être déduite comme un tuple statique et non string[], alors ce sera peut-être possible à l'avenir.

10
Denis