Dis que j'ai une liste const list = ['a', 'b', 'c']
Est-il possible de dériver de ce type d'union de valeurs qui est 'a' | 'b' | 'c'
?
Je veux cela parce que je veux définir un type qui n'autorise que les valeurs du tableau statique et que je dois également énumérer ces valeurs au moment de l'exécution, j'utilise donc array.
Exemple comment il peut être implémenté avec un objet indexé:
const indexed = {a: null, b: null, c: null}
const list = Object.keys(index)
type NeededUnionType = keyof typeof indexed
Je me demande s'il est possible de le faire sans utiliser une carte indexée.
2 réponses
MISE À JOUR Fév 2019
Dans TypeScript 3.4, qui devrait être publié en mars 2019, il sera être possible de dire au compilateur d'inférer le type d'un tuple de littéraux comme un tuple de littéraux , au lieu de, disons, string[]
, en utilisant le as const
syntaxe. Ce type d'assertion amène le compilateur à déduire le type le plus étroit possible pour une valeur, y compris faire tout readonly
. Ça devrait ressembler à ça:
const list = ['a', 'b', 'c'] as const; // TS3.4 syntax
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c';
Cela évitera le besoin d'une fonction d'assistance de quelque nature que ce soit. Bonne chance à tous!
MISE À JOUR juillet 2018
Il semble qu'à partir de TypeScript 3.0, il sera possible pour TypeScript de déduire automatiquement des types de tuple . Une fois publiée, la fonction tuple()
dont vous avez besoin peut être écrite succinctement comme suit:
export type Lit = string | number | boolean | undefined | null | void | {};
export const tuple = <T extends Lit[]>(...args: T) => args;
Et puis vous pouvez l'utiliser comme ceci:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
J'espère que cela fonctionne pour les gens!
MISE À JOUR décembre 2017
Depuis que j'ai publié cette réponse, j'ai trouvé un moyen de déduire des types de tuple si vous êtes prêt à ajouter une fonction à votre bibliothèque. Découvrez la fonction tuple()
dans tuple.ts. En l'utilisant, vous êtes capable d'écrire ce qui suit et de ne pas vous répéter:
const list = tuple('a','b','c'); // type is ['a','b','c']
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'
Bonne chance!
ORIGINAL Juillet 2017
Un problème est que le littéral ['a','b','c']
sera déduit comme type string[]
, donc le système de types oubliera les valeurs spécifiques. Vous pouvez forcer le système de types à mémoriser chaque valeur sous forme de chaîne littérale:
const list = ['a' as 'a','b' as 'b','c' as 'c']; // infers as ('a'|'b'|'c')[]
Ou, peut-être mieux, interprétez la liste comme un type de tuple:
const list: ['a','b','c'] = ['a','b','c']; // tuple
C'est une répétition ennuyeuse, mais au moins, cela n'introduit pas d'objet étranger au moment de l'exécution.
Maintenant, vous pouvez obtenir votre syndicat comme ceci:
type NeededUnionType = typeof list[number]; // 'a'|'b'|'c'.
J'espère que cela pourra aider.
Il n'est pas possible de faire cela avec Array.
La raison est que, même si vous déclarez la variable comme const, le contenu d'un tableau peut encore changer, donc @jonrsharpe mentionne qu'il s'agit du runtime.
Compte tenu de ce que vous voulez, il peut être préférable d'utiliser interface
avec keyof
:
interface X {
a: string,
b: string
}
type Y = keyof X // Y: 'a' | 'b'
Ou enum
:
enum X { a, b, c }
Questions connexes
Questions liées
De nouvelles questions
typescript
TypeScript est un sur-ensemble typé de JavaScript qui se compile en JavaScript brut. Il ajoute des types, classes, interfaces et modules facultatifs à JavaScript. Cette balise est destinée aux questions spécifiques à TypeScript. Il n'est pas utilisé pour les questions JavaScript générales.