How to pass union types through Elm ports?
I've made it work with Json.Decoder/Encoder. Wasn't that difficult after all although having to serialize every single field just to pass that one union type is quite a burden.
Decoders:
modelDecoder : Json.Decoder Model
modelDecoder =
Json.object4 Model
("tasks" := Json.list taskDecoder)
("field" := Json.string)
("uid" := Json.int)
("visibility" := Json.string)
taskDecoder : Json.Decoder Task
taskDecoder =
Json.object5 Task
("description" := Json.string)
("completed" := Json.bool)
("editing" := Json.bool)
("id" := Json.int)
("importance" := Json.string `andThen` importanceDecoder)
importanceDecoder : String -> Json.Decoder Importance
importanceDecoder tag =
case tag of
"Normal" -> Json.succeed Normal
"High" -> Json.succeed High
"Low" -> Json.succeed Low
_ -> Json.fail (tag ++ " is not a recognized tag for Importance")
And encoders:
modelToValue : Model -> Json.Encode.Value
modelToValue model =
Json.Encode.object
[
("tasks", Json.Encode.list (List.map taskToValue model.tasks)),
("field", Json.Encode.string model.field),
("uid", Json.Encode.int model.uid),
("visibility", Json.Encode.string model.visibility)
]
taskToValue : Task -> Json.Encode.Value
taskToValue task =
Json.Encode.object
[
("description", Json.Encode.string task.description),
("completed", Json.Encode.bool task.completed),
("editing", Json.Encode.bool task.editing),
("id", Json.Encode.int task.id),
("importance", importanceToValue task.importance)
]
importanceToValue : Importance -> Json.Encode.Value
importanceToValue importance =
case importance of
Normal -> Json.Encode.string "Normal"
High -> Json.Encode.string "High"
Low -> Json.Encode.string "Low"
You can't pass a union type above all because JS does not know about such a thing. So you might as well pass a string and do a case statement in javascript - I do it all the time.