Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flow: Dynamically generate string union types?

Let's say I have a flow type Suit, and I want to compose it into another type called Card.

// types.js

type Suit =
  | "Diamonds"
  | "Clubs"
  | "Hearts"
  | "Spades";


type Card = {
  ...
  suit: Suit,
  ...
}

Rather than hard-coding in the Suit strings directly in suit.js, is it possible to dynamically generate the Suit type based on a JavaScript primitive (array)? Say...

// constants.js

const SUITS = ['Diamonds', 'Clubs', 'Hearts', 'Spades'];

This way the suits can be defined just once, and inside a JavaScript construct that will for re-use in other sections of the app. For example, a component elsewhere in the app that needs access to all the available suits:

// component.js

SUITS.map((suit: Suit): void => { ... });
like image 559
Jon Cursi Avatar asked Feb 16 '17 16:02

Jon Cursi


1 Answers

This is in fact possible using the utility type $Keys:

const SUITS = {
    Diamonds: 'Diamonds',
    Clubs: 'Clubs',
    Hearts: 'Hearts',
    Spades: 'Spades',
};

type Suit = $Keys<typeof SUITS>

const suit1 : Suit = 'Diamonds'; // OK
const suit2 : Suit = 'Foo'; // Type error

Note that for this example, the values in SUITS don't actually matter, flow will look at the keys in SUITS. type Suit will be like the union type type Suit = 'Diamonds' | 'Clubs' | ...

like image 128
Wietse Venema Avatar answered Oct 18 '22 02:10

Wietse Venema