How do I use the field type of a record in other places in elm

Viewed 171

Consider this:

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

type alias Bar = 
    { id : Foo.id
    , name : String
    }

This does not work in elm to my knowledge. (By this I mean the use of "Foo.id").

I could set the id field in Bar as String but I want it to use the id type of another record. So that when/if I need to refactor it later I can do it in only one place. This is the error message I see when I try to do this *

The type expected 0 arguments, but got 1 instead

Extra Context: I am fairly new to Elm language and functional programming in general. I have a fair bit of Typescript experience. So I am used to creating well defined types. Not sure if that's how its done in Elm. So I'm here to learn and discover.

2 Answers

If you are inclined to deduplicate the type for id field, you may consider extracting it into its own type:

type alias Id = String

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

type alias Bar = 
    { id : Id
    , name : String
    }

You can do something like this. It will wrap strings in an Id AND add a type that helps you enforce proper usage:

    type UserId = UserId -- we have a type called "UserId" who's only value is "UserId"
    
    
    type ProjectId = ProjectId -- ...
    
    
    type Id a = Id String -- an Id has a specific type "a" and is always a wrapper for a string
    
    
    userId : String -> Id UserId
    user = Id -- Id is always a constructor, but the type signature forces Elm to treat this as a "Id UserId". Only code that expects an "Id UserId" can accept this
    
    
    projectId : String -> Id ProjectId
    project = Id


    -- any Id can be turned back into a string
    toString : Id a -> String
    toString (Id a) = a
Related