elm-review rule: forbid using record type alias constructors.
In contrast to lxierita's no-typealias-constructor-call, this rule also reports constructors that aren't called (for example in Json.Decode.mapN functions). ↑ all differences
type alias User =
{ name : String, age : Int }User "Balsa" 42will be marked as error and automatically fixed:
{ name = "Balsa", age = 42 }The same goes for cases where no arguments are applied:
map2 User
(field "name" string)
(field "age" int)fixed
map2 (\name age -> { name = name, age = age })
(field "name" string)
(field "age" int)Fields in a record don't have a "natural order".
{ age = 42, name = "Balsa" }
== { name = "Balsa", age = 42 }
--> TrueSo it shouldn't matter whether you write
type alias User =
{ name : String, age : Int }
or { age : Int, name : String }as well.
User "Balsa" 42however relies on a specific field order in the type and is more difficult to understand/read. These constructors also open up the possibility for bugs to sneak in without the compiler warning you:
type alias User =
{ status : String
, name : String
}
decodeUser : Decoder User
decodeUser =
map2 User
(field "name" string)
(field "status" string)Did you spot the mistake?
To avoid these kinds of bugs, don't use type alias constructors:
decodeUser : Decoder User
decodeUser =
map2 (\name status -> { name = name, status = status })
(field "name" string)
(field "status" string)elm-review --template lue-bird/elm-record-alias-constructor/exampleAfter adding elm-review to your project, import this rule from
your ReviewConfig.elm file and add it to the config. E.g.:
import NoRecordAliasConstructor
import Review.Rule exposing (Rule)
config : List Rule
config =
[ NoRecordAliasConstructor.rule
]lxierita/no-typealias-constructor-call...
(User <| "A") <| 42
(identity User) "Bill" 42
User |> (\user -> user "Bill" 42)aren't reported for exampledecodeUser =
map2 (\name status -> { name = name, status = status })
(field "name" string)
(field "status" string)is rather verbose.
Ultimately, I think elm could introduce some simpler syntax, for example
decodeUser =
map2 (\name status -> { name, status })
(field "name" string)
(field "status" string)like purescript does it or
decodeUser =
map2 { name, status }
(field "name" string)
(field "status" string)(or something crazy using field addition / record unions)