UniquelyTypedID Swift Macro
When passing around strings or integers as IDs, the compiler doesn’t tell you if you pass a person ID where a blog post ID. Now with the UniquelyTypedID
, the compiler will not let you pass the ID of a different model.
And with the power of ExpressibleByStringLiteral
and ExpressibleByIntegerLiteral
, very little code will need to change.
I’ve used this approach for typesafety of record IDs in my own projects, usually by manually copy-pasting. Now with Swift Macros in Swift 5.9, it’s going to be so much easier.
Installation
In Package.swift, add the package to your dependencies.
.package(url: "https://github.com/FullQueueDeveloper/UniquelyTypedID.git", from: "0.1.0"),
And add "UniquelyTypedID"
to the list of your target’s dependencies.
When prompted by Xcode, trust the macro.
Usage
If you had a integer ID
struct BlogPost {
let id: Int
let text: String
}
then you can use this macro instead.
struct BlogPost {
@UniquelyTypedId(Int.self) let id: ID
let text: String
}
Where ID
is the name you desire for your ID type. I tend to use simply ID
, so that I can easily reference the type with BlogPost.ID
Features & supported types
Currently, Int
, String
, and UUID
are supported. The macro defaults to UUID
if no type is specified.
All generated IDs are Hashable
.
All generated IDs are Codable
, and they encode as single value containers, for maximum compatibility when upgrading from plain integer or string IDs.
Strings
String ID types generated by UniquelyTypedId
are expressible by string literal. This makes hardcoded data entry easier.
struct Vegetable {
@UniquelyTypedId(String.self) let scientificName: ScientificName
let name: String
}
let chili = Vegetable(scientificName: "Capsicum annuum", name: "Chili")
And if we encode this chili
to JSON we see
{
"name" : "Chili",
"scientificName" : "Capsicum annuum"
}
Integers
Integer ID types generated by UniquelyTypedId
are expressible by string literal. This makes hardcoded data entry easier.
For example
struct Aubergine: Codable {
@UniquelyTypedID(Int.self) let id: ID
let name: String
}
let aubergineID: Aubergine.ID = 3
let aubergine = Aubergine(id: 9, name: "Fairy Tale")
Swift macros?
Introduced at WWDC ‘23, requiring Swift 5.9
License
BSD-3-Clause
UniquelyTypedID Swift Macro
When passing around strings or integers as IDs, the compiler doesn’t tell you if you pass a person ID where a blog post ID. Now with the
UniquelyTypedID
, the compiler will not let you pass the ID of a different model.And with the power of
ExpressibleByStringLiteral
andExpressibleByIntegerLiteral
, very little code will need to change.I’ve used this approach for typesafety of record IDs in my own projects, usually by manually copy-pasting. Now with Swift Macros in Swift 5.9, it’s going to be so much easier.
Installation
In Package.swift, add the package to your dependencies.
And add
"UniquelyTypedID"
to the list of your target’s dependencies.When prompted by Xcode, trust the macro.
Usage
If you had a integer ID
then you can use this macro instead.
Where
ID
is the name you desire for your ID type. I tend to use simplyID
, so that I can easily reference the type withBlogPost.ID
Features & supported types
Currently,
Int
,String
, andUUID
are supported. The macro defaults toUUID
if no type is specified.All generated IDs are
Hashable
.All generated IDs are
Codable
, and they encode as single value containers, for maximum compatibility when upgrading from plain integer or string IDs.Strings
String ID types generated by
UniquelyTypedId
are expressible by string literal. This makes hardcoded data entry easier.And if we encode this
chili
to JSON we seeIntegers
Integer ID types generated by
UniquelyTypedId
are expressible by string literal. This makes hardcoded data entry easier.For example
Swift macros?
Introduced at WWDC ‘23, requiring Swift 5.9
License
BSD-3-Clause