Maxime Peloquin
Maxime Peloquin

Reputation: 925

Type safe way to handle subset of enum differently

I have an enum and a type that is representing a subset of that enum. I need to handle values in that subset differently than other values. Right now I use a if with multiple conditions, but it might become very large if there are many values in the type.

enum Country {
    Canada,
    Finland,
    France,
    Germany,
    Japan,
    Peru,
}

type EuropeanCountries = Country.Finland | Country.France | Country.Germany;

const NonEuropeanCountriesContinent: Record<
    Exclude<Country, EuropeanCountries>,
    string
> = {
    [Country.Canada]: "America",
    [Country.Japan]: "Asia",
    [Country.Peru]: "America",
}

function getContinent(country: Country) {
    // Here I would like to not have to manually check each value
    if (country === Country.France || country === Country.Finland || country === Country.Germany) {
        return "Europe";
    }

    return NonEuropeanCountriesContinent[country];
}

How can I check if my country variable's value is inside EuropeanCountries without having to manually go through each value of EuropeanCountries?

Playground link

Upvotes: 1

Views: 4665

Answers (1)

Andreas Turku
Andreas Turku

Reputation: 413

If you're going to maintain that record of which enum values belongs to EU, and which do not, then you can use a Custom Type Guard to check type like this:

enum Country {
    Canada,
    Finland,
    France,
    Germany,
    Japan,
    Peru,
}

type EuropeanCountries = Country.Finland | Country.France | Country.Germany;
const EuropeContinent: Record<EuropeanCountries, string> = {
    [Country.Finland]: "Europe",
    [Country.France]: "Europe",
    [Country.Germany]: "Europe",
}
const NonEuropeanCountriesContinent: Record<
    Exclude<Country, EuropeanCountries>,
    string
> = {
    [Country.Canada]: "America",
    [Country.Japan]: "Asia",
    [Country.Peru]: "America",
}

function getContinent(country: Country) {
    if(isInEurope(country)) {
        return EuropeContinent[country];
    }

    return NonEuropeanCountriesContinent[country];
}

function isInEurope(country: EuropeanCountries | Exclude<Country, EuropeanCountries>): country is EuropeanCountries {
    return !!EuropeContinent[country as EuropeanCountries];
}

console.log(getContinent(Country.Finland));
console.log(getContinent(Country.Peru));

Upvotes: 2

Related Questions