Upgrade to Pro — share decks privately, control downloads, hide ads and more …

🏷 Tagged

to4iki
April 19, 2018

🏷 Tagged

potatotips #50
2018/04/19
https://potatotips.connpass.com/event/82476/

`Tagged`を使ったId型作成の話
https://github.com/pointfreeco/swift-tagged

to4iki

April 19, 2018
Tweet

More Decks by to4iki

Other Decks in Programming

Transcript

  1. ex. 1 struct User: Decodable { typealias Id = String

    let id: Id let subscriptionId: Subscription.Id } struct Subscription: Decodable { typealias Id = String let id: Id } 4
  2. ! not type-safety // typealias User.Id = String func fetchUser(with

    id: User.Id) -> User? fetchUser(with: user.id) // OK fetchUser(with: user.subscriptionId) // OK fetchUser(with: "123") // OK 5
  3. ! type-safety struct User: Decodable { struct Id: Decodable {

    let value: String } ... } func fetchUser(with id: User.Id) -> User? fetchUser(with: user.id) // OK fetchUser(with: user.subscriptionId) // Compile Error fetchUser(with: "123") // Compile Error 6
  4. ex. 2 { "id": "abc", "subscriptionId": "123" } // decode

    to `User` let decoder = JSONDecoder() let user = try! decoder.decode(User.self, from: Data(json.utf8)) 7
  5. ! DecodingError.typeMismatch at User.Id Fatal error: 'try!' expression unexpectedly raised

    an error: Swift.DecodingError.typeMismatch(Swift.Dictionary<Swift.Strin g, Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "id", intValue: nil)], debugDescription: ... 8
  6. ! DecodableΛ໌ࣔతʹ࣮૷͢Δ struct User: Decodable { struct Id: Decodable {

    let value: String init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() self.value = try container.decode(String.self) } } ... } 9
  7. SE-0143: Conditional Conformance1 /// Swift4 /// Returns `true` if these

    arrays contain the same elements. public func ==<Element>(lhs: [Element], rhs: [Element]) -> Bool where Element : Equatable /// Swift4.1 extension Array: Equatable where Element: Equatable { static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool } [1,2,3] == [1,2,3] // ok 1 https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md 11
  8. use Tagged struct User: Decodable, Equatable... { typealias Id =

    Tagged<User, String> let id: Id let subscriptionId: Subscription.Id } struct Subscription: Decodable, Equatable... { typealias Id = Tagged<Subscription, String> let id: Id } 14
  9. use Tagged "Decodable" let decoder = JSONDecoder() let user =

    try! decoder.decode(User.self, from: Data(json.utf8)) "Equatable" user1 == user2 // OK 15
  10. https://github.com/pointfreeco/swift-tagged/blob/master/Sources/Tagged/Tagged.swift public struct Tagged<Tag, RawValue> { public var rawValue: RawValue

    public init(rawValue: RawValue) { self.rawValue = rawValue } } extension Tagged: RawRepresentable { } 16
  11. https://github.com/pointfreeco/swift-tagged/blob/master/Sources/Tagged/Tagged.swift extension Tagged: Comparable where RawValue: Comparable { extension Tagged:

    Decodable where RawValue: Decodable { extension Tagged: Encodable where RawValue: Encodable { extension Tagged: Hashable where RawValue: Hashable { extension Tagged: Numeric where RawValue: Numeric { extension Tagged: ExpressibleByStringLiteral where RawValue: ExpressibleByStringLiteral { ... 17
  12. Conclusion • Swift 4.1 Conditional Conformance ʹΑΓܕͷදݱྗ͕๛ ͔ʹͳͬͨ • Tagged

    Λ࢖͏͜ͱͰϓϦϛςΟϒ3ͳܕΛ؆୯ʹܕԽ͢Δ͜ ͱ͕Ͱ͖Δ 3 ೚ҙͷܕͰߏΘͳ͍͕ຊεϥΠυͷྫʹԊͬͯ͜ͷΑ͏ʹදݱ͍ͯ͠Δ 18