9

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?

noah
  • 21,289
  • 17
  • 64
  • 88

4 Answers4

8

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.

Chad Gilbert
  • 36,115
  • 4
  • 89
  • 97
  • Appending a single quote does not escape the field name, though, it changes it to a different name. – noah Jan 20 '16 at 14:15
  • I've updated my answer to show how the field name in JSON does not need to match the Elm field it gets decoded to. – Chad Gilbert Jan 20 '16 at 14:22
  • Using a single quote in the name goes really wrong in Elm 0.16 at least. It becomes the start of a string literal in generated JS. Using _ instead works well. – Alex Korban Apr 26 '16 at 00:35
  • @AlexKorban - I haven't had a problem in Elm 0.16. Defining this `foo'bar' = "asdf"` works just fine. – Chad Gilbert Apr 26 '16 at 14:34
  • I run into `Ran into a single quote in a variable name. This was removed in 0.18!` error with this solution. – Dwayne Forde Feb 01 '19 at 23:11
3

You can now escape the keyword with an underscore.

ex.

type alias Foo =
  { id: String
  , type_: String
}
Dwayne Forde
  • 1,324
  • 13
  • 13
2

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)
Bzzt
  • 1,064
  • 8
  • 13
-1

There is no escape. Elm is uncompromising.

noah
  • 21,289
  • 17
  • 64
  • 88
  • kind of a harsh behaviour. What if someone is working with an API which he doesn't control? – marcosh Jan 20 '16 at 09:44
  • @marcosh well you can translate the keyword to another field/varable name, and that name is only used within Elm. If you export to JS via a port, you'll have to encode it back. So the field name wont match the JSON property name exactly, but it's not a barrier to working with any sort of JSON. Just annoying IMO – noah Jan 20 '16 at 18:35