web-dev-qa-db-fra.com

Comment décrire la forme de la carte Immutable.js avec Flow

Je voudrais décrire la forme d'une carte en utilisant les définitions de type de flux d'Immutable.

Vous pouvez décrire la forme d'un objet en:

const stateShape: {
  id: number,
  isActive: boolean
} = {
  id: 123,
  isActive: true
};

Y a-t-il quelque chose de similaire pour les cartes d'Immutable?

40
William

TL; DR;

Non, mais en utilisant Records, vous pouvez demander à Flow de vérifier la forme mais pas les types.

Forme longue

La réponse correcte serait: non, car les cartes n'ont pas de formes (au moins dans Flux et immuable). Mais Immuable a un type pour "Maps" avec des formes. Ce serait Records . Mais pour les raisons décrites ci-dessous (car ce n'est pas strictement pertinent), le flux libdef pour Immutable.Record Est très lâche et ne vérifie pas les formes.

Un meilleur dossier libdef

Si nous ignorons la fonction (sans doute inutile) d'accéder directement aux propriétés Record, nous pouvons créer un meilleur libdef. Le ressemblerait à ceci:

declare class Record<T: Object> {
  static <T: Object>(spec: T, name?: string): Record<T>;
  get: <A>(key: $Keys<T>) => A;
  set<A>(key: $Keys<T>, value: A): Record<T>;
  remove(key: $Keys<T>): Record<T>;
}

Avec cette déclaration, nous pouvons définir la forme de l'enregistrement . Ici c'est en action . Mais nous ne pouvons toujours pas définir les types des valeurs réelles. Le flux définit un type $PropertyType<T, K> Non documenté. Ce qui prend un objet T et une chaîne littérale K. Pour que $PropertyType Fonctionne dans notre cas, il devrait fonctionner pour $Keys<T> Qui est un type d'union de chaîne. Il y a quelques semaines, un problème a été ouvert pour que cela se produise. Il peut être trouvé ici .

Différence entre la carte et l'objet

En flux, ils sont assez différents. Voici une carte:

type MyMaps = { [key: string]: number }

Les clés réelles sont inconnues. La seule chose que Flow sait, c'est que toutes les clés doivent être des chaînes et toutes les valeurs doivent être des nombres. En revanche, un type d'objet ressemble à:

type MyObject = { a: string, x: boolean }

Lors de la création ou de la modification d'un objet, newObj, de type MyObject Flow, vérifiera que newObj.a Est une chaîne et newObj.x Est un booléen.

Pourquoi la définition actuelle est si vague

Un enregistrement expose chaque paire clé/valeur via un accès direct à la clé.

type R = { a: string }
const r = Record({ a: 'Supa' })
r.a === r.get('a')

Cela nécessiterait que la définition de type de r soit une intersection de Record<R> Et R (pas exactement, mais c'est assez proche). Donc:

(r: R & Record<R>)

Cela ne fonctionne pas car Flow ne prend pas en charge les types d'intersection avec des objets. Voici à quoi cela ressemble en action .

29
Kriegslustig