1
votes

Comment utiliser la valeur de chaîne comme type littéral dans Flowtype?

Typescript me permet d'avoir une définition comme:

export const LineType = {
  Adventure: "Adventure",
  Lift: "Lift"
}
Object.freeze(LineType);
export type LineTypeEnum = $Enum<typeof LineType>;

export type AdventureLine =
{
  type: LineType.Adventure;
}

Je peux faire des choses similaires dans Flow:

export enum LineType {
  Adventure,
  Lift
}

export type AdventureLine =
{
  type: LineType.Adventure;
}

mais ce n'est pas le cas t compilez type: LineType.Adventure; - Le flux dit: "Impossible d'utiliser la chaîne comme type". Bien sûr, je pourrais écrire type: "Adventure"; , mais ce n'est pas très DRY.

Alors, comment utiliser une valeur de chaîne comme type littéral dans Flow?


0 commentaires

3 Réponses :


1
votes

Would quelque chose comme ce travail pour vous?

type LineType = { Adventure: "Adventure", Lift: "Lift" };
type AdventureLine = { type: $PropertyType<LineType, 'Adventure'> };

({ type: "Adventure" }: AdventureLine); // no error
({ type: "Lift" }: AdventureLine); // error


3 commentaires

Non, pas vraiment. Parce que vous avez changé LineType en un type à partir d'un objet. Il ne peut donc pas être utilisé de la manière dont les énumérations sont utilisées: const geometryType = LineType.Adventure;


Ensuite, je ne suis pas sûr d'un moyen de le faire. Flow ne semble pas avoir de parallèle avec enum car JS n'a pas ce concept intégré dans le langage. Ce serait cool si typeof pouvait être contrôlé pour le niveau de détail du type renvoyé (ainsi, par exemple, typeof LineType.Adventure de votre exemple serait " Adventure " au lieu de string . Jetez également un œil à cette proposition pour ajouter des énumérations à Flow.


Pour le moment, je viens de faire "taper: LineType & 'Adventure'". Cette instruction à elle seule n'a pas de sécurité de compilation appropriée, c'est-à-dire que vous pouvez donner une chaîne erronée comme "ABC". Bien que dans ce cas, cela ne vous permettra pas du tout de créer l'objet, donc je suppose que c'est mieux que rien ...



2
votes

Qu'en est- cette ?

const Adventure: "Adventure" = "Adventure";
const Lift: "Lift" = "Lift";

export const LineType = {  Adventure,  Lift };
Object.freeze(LineType);
export type LineTypeEnum = $Enum<typeof LineType>;

export type AdventureLine =
{
  type: typeof LineType.Adventure;
}

({ type: "Adventure" }: AdventureLine); // works

({ type: "x" }: AdventureLine); // gives erros


1 commentaires

Joli! C'est un peu répétitif, mais uniquement dans la définition. Cela semble faire le travail. J'aimerais qu'il y ait quelque chose de plus simple ... (comme dans TS :))



0
votes

(Je sais que c'est une vieille question, mais elle apparaît dans les résultats de recherche, je voulais donc répondre correctement à la façon de le faire avec Flow moderne.)

Je pense que la façon d'accomplir ce que vous voulez est d'utiliser le Opérateur utilitaire $ Keys .

https://flow.org/en/docs/types/utilities/#toc-keys

// @flow
const LineTypes = {
  Adventure: "Adventure",
  Lift: "Lift",
}

type LineType = $Keys<typeof LineTypes>

const geometryType = LineTypes.Adventure
const AdventureLine: LineType = 'Adventure'

// $ExpectError
const wontWork: LineType = 'Foo'


8 commentaires

Non, cela ne résout pas mon problème. Je dois admettre que ma question est alambiquée - j'ai dû la lire moi-même quelques fois avant de comprendre ce que j'étais après :) De toute façon, le problème est que je ne peux pas utiliser LineType.Adventure comme un type (pas comme valeur!). Essayez simplement de définir un type comme celui-ci: export type AdventureLine = {type: LineType.Adventure; }


L'opérateur utilitaire $ PropertyType utilisé par @ user11307804 peut également être utilisé dans ce cas, bien qu'il soit assez détaillé: Essayez flux


Alors, quelle est la différence entre $ PropertyType et typeof LineType.Adventure ? De plus, ce code compile bien const a: AdventureLineAsAType = {type: "moo"} dans votre cas alors qu'il ne le devrait pas, car le type de résultat est string . Consultez cette réponse pour le résoudre: stackoverflow.com/a/56717886/217022


Ah merci. Je n'ai pas vraiment compris ce que vous recherchiez au début. J'ai essayé quelques tentatives supplémentaires (que je publierai en tant que commentaire séparé en raison de la limite de caractères). Malheureusement, alors que $ Values ​​ affine correctement le type d'objets Frozen en littéraux de chaîne, $ PropertyType l'étend toujours en chaîne. Donc, finalement, je pense que la réponse d'Alex Savin est vraiment le meilleur moyen.


Plus de tentatives avec objet Frozen et $ Valeurs <> : Essayer Flow


vous n'avez pas besoin de valeurs gelées ou de $ Values ​​pour définir un type comme ça, je veux dire si vous vous répétez en disant type: "Adventure"


Je ne savais pas non plus que $ Values ​​ obtenait le type correct sur les objets gelés. Merci pour cet indice!


Oui, je les ai laissés là-dedans pour que vous puissiez voir le problème avec $ PropertyType si vous le souhaitez. Comme vous le dites, n'en avez pas besoin si vous utilisez de toute façon une «aventure» explicite. Si une utilisation plus traditionnelle de style Enum est intéressante, cette réponse montre une manière claire avec freeze et $Values<> .