- native TS langugae server (which IDEs use by default) supports jumping to usages of enum keys (pretty sure it's possible to do this with unions using extensions/JetBrains, but it's not built-in into vscode at the moment)
- more familiar (as it's used in many programming languages)
- could be easily extended:
type UkCity = "london" | "edinburgh" type SupportedCIty = UkCity | "dublin"
- More concise
enum AllowedCities { london = 'london' edinburgh = 'edinburgh' } // vs type AllowedCities = 'london' | 'edinburgh' const isAllowedCity = (c) => Object.values(AllowedCities).includes(c) // vs const isAllowedCity = (c) => AllowedCities.includes(c) import { AllowedCities } from '...' findVendors(AllowedCities.edinburgh) // vs findVendors('edinburgh') // no need to import
- Could be derived from bigger objects:
const SUPPORTED_CITIES = { london: { phone: "+44......', currency: "GBP", }, dublin: { phone: "....", currency: "EUR", }, } as const type SupportedCities = typeof SUPPORTED_CITIES // derive type of allowed cities without declaring them again type SupportedCity = keyof SupportedCities // "london" | "dublin" // derive type of allowed currencies without declaring them again type SupportedCurrency = SupportedCities[SupportedCity]["currency"] // "GBP" | "EUR"
- Could be used with other unions where the type are the same, whilist enums can't:
This is an issue when we have no control where an enum comes from (e.g. we have an enum auto-generated by graphql codegen and a helper with a matching enum declared in an npm package)
// these two enums will always have same values enum CitiesX { London } enum CitiesY { London } const doSomething = (c: CitiesX) => ... // will error even though the keys/values of the two enums are compatible with each other doSomething(CitiesY.London)
- Less typing when using
e.g.
'lon<auto-complete>
vsCi<auto-complete>.<auto-complete>
(plus need to (auto)import)