Flow: How to check if value is in enum (union of string values)?

Created on 8 Dec 2016  路  5Comments  路  Source: facebook/flow

// @flow

type countryCodeType = 'gb' | 'us';

const countryCodes = [
  'gb',
  'us'
];

const getSiteCountryCode0 = (userInput: string): countryCodeType => {
  const countryCodeIndex = countryCodes.indexOf(userInput);

  if (countryCodeIndex === -1) {
    throw new Error('Unexpected country code.');
  }

  return countryCodes[countryCodeIndex];
};

const getSiteCountryCode1 = (userInput: string): countryCodeType => {
  if (!countryCodes.includes(userInput)) {
    throw new Error('Unexpected country code.');
  }

  return userInput;
};

I cannot figure out how to make the above work:

https://flowtype.org/try/#0PTAEAEDMBsHsHcBQiAuBPADgU1AY1gK4B2KATmgMKwAmWAKpjgLygDkA5gEaugA+bBAM6sA3MnxFBKPIRLkqtQaBYBtRKDZdWAGnUDhiALpjEEqaHZYUAZQCWKLFWJlKNLAAZloABRCspAEkiDAIUAC5QKVJbInYASgj8Z3k3BmxlAD5QAG89M2kkuVdaINoADy9ClwUsQQA6GPKAeUhfQX8gkJQ4sQ09W0gfKpSSonLlJhYAWgBGOJy9AEgUAAtSBFAiLHhQAFFSddJvVgBVLbLsXAdqGWS0GVo61h69AF89PVIrAlIiW6KaoIVMNilhSlgysZEK8TPkLFY7A4nAC3DMvG0OsFQhEojF4olZNVUoxMgsNAMfABCEGAhpEXDQAiKDGBLHdea5DQaVbrHZbHb7Q7HM4Qy7Xf4uB5YJ4vDTvPoaL4oH5-PysrpiGHIIA

Most helpful comment

Using find?

// @flow

type countryCodeType = 'gb' | 'us';

const countryCodes: Array<countryCodeType> = [
  'gb',
  'us'
];

const getSiteCountryCode = (userInput: string): countryCodeType => {
  const maybe = countryCodes.find(v => v === userInput)  
  if (!maybe) {
    throw new Error('Unexpected country code.');
  }
  return maybe;
};

try

All 5 comments

I realised countryCodes is missing Array<string> cast. However, even after casting it to Array<string> the second example reports an error:

// @flow

type countryCodeType = 'gb' | 'us';

const countryCodes: Array<string> = [
  'gb',
  'us'
];

const getSiteCountryCode1 = (userInput: string): countryCodeType => {
  if (!countryCodes.includes(userInput)) {
    throw new Error('Unexpected country code.');
  }

  return userInput;
};

https://flowtype.org/try/#0PTAEAEDMBsHsHcBQiAuBPADgU1AY1gK4B2KATmgMKwAmWAKpjgLygDkA5gEaugA+bBAM6sA3MnxFBKPIRLkqtQQC5QAQVKkAhmgA8U0gEsi7AHygWAbUSg2XVgBprA4YgC6YxBKmh2WFAGUDFCwqYjJKGiwARnNQAAohLFIASSIMAhQVfSN2AEoVfDD5SIZsczMAbycDSHiAQkK5CMUAOiNcaAJFBMEk1PSUXNzQKpsbFAALUgRQIix4UABRDVhSONYAVTmAD2xcYOoZIrQZWhbWXLEbAF8nJ1I-AlIiUESUtIyxa48gA

The first example works:

const getSiteCountryCode0 = (userInput: string): countryCodeType => {
  const countryCodeIndex = countryCodes.indexOf(userInput);

  if (countryCodeIndex === -1) {
    throw new Error('Unexpected country code.');
  }

  return countryCodes[countryCodeIndex];
};

I have also tried:

const countryCodes: Array<countryCodeType > = [
  'gb',
  'us'
];

but that produces different set of errors.

Using find?

// @flow

type countryCodeType = 'gb' | 'us';

const countryCodes: Array<countryCodeType> = [
  'gb',
  'us'
];

const getSiteCountryCode = (userInput: string): countryCodeType => {
  const maybe = countryCodes.find(v => v === userInput)  
  if (!maybe) {
    throw new Error('Unexpected country code.');
  }
  return maybe;
};

try

Thank you @gcanti.

So just for clarification, why _doesn't_ indexOf or includes work in this case? I would expect the behavior to be the same in all three cases.


Edit: Ok, I kind of understand now that I read a few threads like this one.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mjj2000 picture mjj2000  路  3Comments

funtaps picture funtaps  路  3Comments

jamiebuilds picture jamiebuilds  路  3Comments

Beingbook picture Beingbook  路  3Comments

glenjamin picture glenjamin  路  3Comments