Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Swift-like enums with associated values in JavaScript?

Tags:

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 ints).


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?

like image 977
Janum Trivedi Avatar asked Jan 30 '16 19:01

Janum Trivedi


People also ask

Why Swift enums with associated values Cannot have a raw value?

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.

Can you give useful examples of enum associated values?

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.

What is associated type in enum?

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.

Can you make enums in JavaScript?

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.


1 Answers

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;   }  } 
like image 78
jdeff Avatar answered Nov 21 '22 04:11

jdeff