Dan Pettis
Dan Pettis

Reputation: 123

How to check if value exists inside javascript Flow type

I have a Flow type defined as

export type fruit = 'apple' | 'orange' | 'pear';

What I want to do is validate a string and see if it matches any of the values defined in this type.

Is there a way to do this?

Upvotes: 3

Views: 260

Answers (3)

Ben Flynn
Ben Flynn

Reputation: 18922

This is definitely kind of clunky, build you could also do:

type FruitMap = {
  apple: '',
  pear: '',
}

const FRUIT_MAP: FruitMap = Object.freeze({
  apple: '',
  pear: '',
});

type Fruit = $Keys<FruitMap>;

const apple = 'apple';
const isFruit = Object.keys(FRUIT_MAP).includes(apple);

Upvotes: 0

Brianzchen
Brianzchen

Reputation: 1335

If you are talking about type refinement from a string into one of these values, there's not currently an elegant way of doing this.

A very similar issue was posted here a few days ago here and an issue raised here.

To do this with flow and not get errors you need to manually type out the combinations using either an if statement or switch statement,

try

// @flow
type fruit = 'apple' | 'orange' | 'pear';

const func = (f: string): fruit | void => {
  const fruits = ['apple', 'orange', 'pear'];
  if (fruits.includes(f)) {
    return f; // This one errors out because you cannot type refine using
  }
}

const func2 = (f: string): fruit | void => {
  if (f === 'apple' || f === 'orange' || f === 'pear') {
    return f;
  }
}

const func3 = (f: string): fruit | void => {
  switch (f) {
    case 'apple':
    case 'orange':
    case 'pear':
      return f;
  }
}

Upvotes: 0

Nguyễn Văn Phong
Nguyễn Văn Phong

Reputation: 14208

The best approach is to use an array then validate by using Array#includes like this.

const fruits = ['apple', 'orange', 'pear'];
const isValid = anyFruit => fruits.includes(anyFruit);

console.log(isValid("apple"));
console.log(isValid("orange"));
console.log(isValid("pear"));
console.log(isValid("banana"));

Upvotes: 1

Related Questions