struct Identifier<Value>: Hashable {
let string: String
}
Now userId can be of type Identifier<User>
We can also use the extension ExpressibleByStringLiteral to give us convenience of passing the identifier as string literals directly. e.g. without: User(id: Identifier(string: "123")) vs with: User(id: "123")
Perhaps the only minor concern I have is how we can easily adapt these changes for our storage facade. Now we have to extract the string literals as well when storing (i.e instead of message.senderId, we might need something like message.senderId.string). But this is trivial and can be ignored
But a more important thing is iirc our View would require these ID strings somewhere (i forgot where ooops). I don't think we can use Identifier<User> and the likes, because in such a scenario, it would mean View would depend on the Model already.
Currently, we represent all the
id
usingString
, which does not have a Type Safety guarantee (e.g.userId
can be passed as anid
for Messages).I came across this article: https://www.swiftbysundell.com/articles/type-safe-identifiers-in-swift/
The idea is to define this struct:
Now
userId
can be of typeIdentifier<User>
We can also use the extension
ExpressibleByStringLiteral
to give us convenience of passing the identifier as string literals directly. e.g. without:User(id: Identifier(string: "123"))
vs with:User(id: "123")
Perhaps the only minor concern I have is how we can easily adapt these changes for our storage facade. Now we have to extract the string literals as well when storing (i.e instead of
message.senderId
, we might need something likemessage.senderId.string
). But this is trivial and can be ignoredBut a more important thing is iirc our
View
would require these ID strings somewhere (i forgot where ooops). I don't think we can useIdentifier<User>
and the likes, because in such a scenario, it would meanView
would depend on theModel
already.