Coder Social home page Coder Social logo

swift-tagged's Introduction

๐Ÿท Tagged

MacOS CircleCI Linux Build Status

A library for safer types.

Introduction

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.

For example, an email address is nothing but a String, but it should be restricted in the ways in which it can be used. And while a User id may be represented with an Int, it should be distinguishable from an Int-based Subscription id.

Examples

Tagged lets us wrap basic types in more specific contexts with ease. Given the following JSON representing a user:

{
  "id": 1,
  "email": "[email protected]",
  "subscriptionId": 1
}

We may be tempted to model it simply:

struct User: Decodable {
  let id: Int
  let email: String
  let subscriptionId: Int?
}

struct Subscription: Decodable {
  let id: Int
}

It's easy to model user and subscription ids using the same type, but our app logic shouldn't treat these values interchangeably: doing so could lead to runtime bugs and security issues!

Luckily, we can use Tagged to differentiate these types.

import Tagged

struct User: Decodable {
  typealias Id = Tagged<User, Int>

  let id: Id
  let email: String
  let subscriptionId: Subscription.Id?
}

struct Subscription: Decodable {
  typealias Id = Tagged<Subscription, Int>

  let id: Id
}

Now there's no chance we'll accidentally pass a User id where we expect a Subscription id.

Tagged depends on a generic "tag" parameter to make each type unique. In these cases, we use the parent type to tag each Id type.

What if there's no parent type? Let's say we want to constrain an Email type that wraps a string.

typealias Email = Tagged<_, String>

We can tag Email by defining an uninhabited EmailTag enum.

enum EmailTag {}
typealias Email = Tagged<EmailTag, String>

Now our User can be even more type-safe.

struct User: Decodable {
  typealias Id = Tagged<User, Int>

  let id: Id
  let email: Email
  let subscriptionId: Subscription.Id?
}

Tagged relies on conditional conformance to be practical: if the raw values are encodable or decodable, equatable, hashable, or comparable, the tagged values follow suit.

Tagged types also inherit any literal expressibility. Our User type above can be instantiated simply using the underlying literals.

User(
  id: 1,
  email: "[email protected]",
  subscriptionId: 1
)

Installation

Carthage

If you use Carthage, you can add the following dependency to your Cartfile:

github "pointfreeco/swift-tagged" ~> 0.1

CocoaPods

If your project uses CocoaPods, just add the following to your Podfile:

pod 'Tagged', '~> 0.1'

SwiftPM

If you want to use Tagged in a project that uses SwiftPM, it's as simple as adding a dependencies clause to your Package.swift:

dependencies: [
  .package(url: "https://github.com/pointfreeco/swift-tagged.git", from: "0.1.0")
]

Xcode Sub-project

Submodule, clone, or download Tagged, and drag Tagged.xcodeproj into your project.

Interested in learning more?

These concepts (and more) are explored thoroughly in Point-Free.

License

All modules are released under the MIT license. See LICENSE for details.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.