Skip to content

davdroman/swift-tagged-macro

Repository files navigation

#Tagged

CI

A Swift macro built on top of Point-Free's Tagged library, with one key improvement: zero boilerplate, even in cases of collision.

Motivation

We often work with types that are far too general or hold far too many values than what is necessary for our domain. Sometimes we just want to differentiate between two seemingly equivalent values at the type level.

Tagged solves this, but handling tag collisions for the same underlying types quickly becomes verbose:

struct User {
    enum EmailTag {}
    enum AddressTag {}
    typealias Email = Tagged<EmailTag, String>
    typealias Address = Tagged<AddressTag, String>
}

You can also use tuple tricks:

struct User {
    typealias Email = Tagged<(User, email: ()), String>
    typealias Address = Tagged<(User, address: ()), String>
}

But this is still quite verbose, not very memorable, and can lead to collisions if not careful.

With #Tagged, you can just write:

struct User {
    #Tagged<String>("Email")
    #Tagged<String>("Address")
}

Which expands to:

struct User {
    typealias Email = Tagged<(User, Email: ()), String>
    typealias Address = Tagged<(User, Address: ()), String>
}

Installation

.package(url: "https://github.com/davdroman/swift-tagged-macro", from: "0.1.0"),
.product(name: "TaggedMacro", package: "swift-tagged-macro"),

About

A zero-boilerplate macro for Point-Free's Tagged type

Resources

License

Stars

Watchers

Forks

Languages