The Swift language has a fantastic enum support. Not only can one define a standard enum with cases, but cases can have optional values "associated to them."
For example, taken from the Swift docs:
enum Barcode { case UPCA(Int, Int, Int, Int) case QRCode(String) case Other }
Such that one could create a Barcode enum by passing in a value, like so:
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
and also switch
on productBarcode
at a later date to retrieve the associated value (a tuple of int
s).
I have been trying to implement this kind of enum
system in JavaScript (ES5, in particular), but am hitting a wall. What is the best way to structure an enum system, especially one with associated values?
We had to do this because Swift doesn't allow us to have both: raw values and associated values within the same enum. A Swift enum can either have raw values or associated values. Why is that? It's because of the definition of a raw value: A raw value is something that uniquely identifies a value of a particular type.
For instance, you might describe a weather enum that lists sunny, windy, and rainy as cases, but has an associated value for cloudy so that you can store the cloud coverage. Or you might describe types of houses, with the number of bedrooms being an associated integer.
An enum cannot have both raw values and associated values at the same time. The raw values of an enum must be of the same data type. But associated values can be of any type.
Enums are not supported in JavaScript natively. We can however create Enums using Object. freeze by creating objects containing all the enumerable properties and then freezing the object so that no new enum can be added to it.
You can use a discriminated union for this. This example uses Typescript, but the concept would be similar for Javascript just without the type safety.
interface UPCA { kind: "UPCA"; numberSystem: number; manufacturer: number; item: number; checkDigit: number; } interface QRCode { kind: "QRCode"; data: string; } interface Other { kind: "Other"; } type Barcode = UPCA | QRCode | Other;
You can then switch over a value of Barcode
and access the associated values after checking the discriminate.
function printBarcode(barcode: Barcode) { switch (barcode.kind) { case "UPCA": console.log(`UPCA: ${barcode.numberSystem}-${barcode.manufacturer}`); break; case "QRCode": console.log(`QRCode: ${barcode.data}`); break; case "Other": console.log("Other barcode"); break; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With