Search code examples
swiftgenericstype-constraints

Swift Generic Type Constraint with or operator


I am trying to make protocol which generic types are limited to types can be saved to UserDefaults.

Is it possible to have type constraints with either conforms to a specific type or another specific type?

For example code below works.

public protocol UserDefaultsRequestType {

    associatedtype ValueToSet where ValueToSet == URL

    var valueToSet: ValueToSet { get }
}

Something I want achieve is like the blow

public protocol UserDefaultsRequestType {

    // Value should either be a type URL, String or Bool
    associatedtype ValueToSet where ValueToSet == URL || ValueToSet == String || ValueToSet == Bool

    var valueToSet: ValueToSet { get }
}


Solution

  • This look more like a XOR, since a variable can't be an URL and a String at the same time but to answer you question you can't do it!

    But I think you already know that since the compiler probably told you :

    Consecutive declarations on a line must be separated by ';'

    But if you want ValueToSet to be either URL, String or Bool It should be because these 3 types have something that you need in common, and it means a conformance to a protocol or inheritance from a base class.

    The 3 types you gave conforms

    • CKRecordValueProtocol
    • CustomReflectable
    • CustomStringConvertible
    • CVarArg
    • Decodable
    • Encodable
    • Equatable
    • Hashable
    • MLDataValueConvertible

    So let's say you want to be able to use them as keys in a Dictionary you could write :

    associatedtype ValueToSet where ValueToSet: Hashable
    

    Meaning that ValueToSet can be ANY type conforming to Hashable.

    But since you seem to be working with UserDefaults and it's public methods to set default values are not using protocols nor classes.

    eg:

    func set(_ url: URL?, forKey defaultName: String)
    

    This approach won't get you far, the one proposed by Sweeper is probably best for you.