9
votes

I have some JSON with a "type" property that I want to import into Elm. e.g., { "id": "abc", "type": "thing" } However if I define a type alias with type as a property, the compiler complains. e.g.,

type alias Foo = {
      id: String
    , type: String
}

produces

It looks like the keyword `type` is being used as a variable.

3│     , type: String
              ^
Rename it to something else.

Seriously? I have to rename the property? Is there no way to quote or escape it so it will compile?

4

4 Answers

8
votes

Yes, type is a reserved keyword and cannot be used as a field name in a record.

In Elm and Haskell, the most common thing to do in your case seems to be to append a single quote, so it becomes type', and your type definition becomes

type alias Foo =
  { id: String
  , type': String
  }

This has its origin in the prime symbol from mathematics. It may look odd at first but it is valid syntax.

You can then use the following Json Decoder to translate the JSON into Foo:

fooDecoder =
  Json.object2
    Foo
    ("id" := Json.string)
    ("type" := Json.string)

Notice that the exact field name in Elm does not need to match the JSON field name.

Rarely will you find a language that lets you use keywords as variable names unescaped. This behavior is not unique to Elm.

3
votes

You can now escape the keyword with an underscore.

ex.

type alias Foo =
  { id: String
  , type_: String
}
2
votes

In oscpad, I'm using a "type" field in my json interface over websockets. But I don't have a field called type in an elm record. I just look for a "type" field when I'm parsing JSON. My code looks like this:

jsSpec : JD.Decoder Spec
jsSpec =
  ("type" := JD.string) `JD.andThen` jsCs

jsCs : String -> JD.Decoder Spec
jsCs t =
  case t of
    "button" -> SvgButton.jsSpec `JD.andThen` (\a -> JD.succeed (CsButton a))
    "slider" -> SvgSlider.jsSpec `JD.andThen` (\a -> JD.succeed (CsSlider a))
    "label" -> SvgLabel.jsSpec `JD.andThen` (\a -> JD.succeed (CsLabel a))
    "sizer" -> jsSzSpec `JD.andThen` (\a -> JD.succeed (CsSizer a))
    _ -> JD.fail ("unkown type: " ++ t)
-1
votes

There is no escape. Elm is uncompromising.