Nader
Nader

Reputation: 1148

Invalid redeclaration of typealias

I have a generic protocol, TwoWayBindDelegate, that uses the generic associated type to determine the parameters of the function twoWayBind()

protocol TwoWayBindDelegate: class {

    associatedtype BindType

    func twoWayBind(to observable: Observable<BindType>?, observableChanged: ((BindType) -> ())?)
}

I then created a class, Reactive<Base: UIView, Type> (which conforms to TwoWayBindDelegate) where you have to initialize it with the generic Base. For eg: let reactiveSlider = Reacive<UISlider>(slider).

My issue is when I am extending Reactive and conforming to TwoWayBindDelegate, I get an error Invalid redeclaration of 'BindType' because I am declaring BindType and twoWayBind() in both my extensions. Is there a way I can have both extensions provide different implementations for TwoWayBindDelegate

class Reactive<Base: UIView>: TwoWayBindDelegate {

    public var base: Base

    init(base: Base) {
        self.base = base
    }
}

extension Reactive where Base == UISlider {

    typealias BindType = Float        

    func twoWayBind(to observable: Observable<Float>?, observableChanged: ((Float) -> ())?) {
        // implement two way bind for UISlider
    }
}

extension Reactive where Base == UITextField {

    typealias BindType = String        

    func twoWayBind(to observable: Observable<String>?, observableChanged: ((String) -> ())?) {
        // implement two way bind for UITextField
    }
}

I did some research and found out that it may be a bug https://bugs.swift.org/browse/SR-5392. Does there happen to be a workaround

Upvotes: 1

Views: 755

Answers (1)

matt
matt

Reputation: 535557

I don't quite see what the typealias is for. The function declaration alone is sufficient to tell the compiler what BindType must be.

The problem I found with your code (apart from the missing Observable declaration, of course) is that the Reactive class itself doesn't conform to TwoWayBindDelegate. To get around that, I threw in an arbitrary implementation of twoWayBind. When I did, and when I deleted the unnecessary typealias declarations, your code compiled for me:

struct Observable<T> {}

protocol TwoWayBindDelegate: class {
    associatedtype BindType
    func twoWayBind(to observable: Observable<BindType>?, observableChanged: ((BindType) -> ())?)
}

class Reactive<Base: UIView>: TwoWayBindDelegate {
    public var base: Base
    init(base: Base) {
        self.base = base
    }
    func twoWayBind(to observable: Observable<Int>?, observableChanged: ((Int) -> ())?) {
    }
}

extension Reactive where Base == UISlider {
    func twoWayBind(to observable: Observable<Float>?, observableChanged: ((Float) -> ())?) {
    }
}

extension Reactive where Base == UITextField {
    func twoWayBind(to observable: Observable<String>?, observableChanged: ((String) -> ())?) {
    }
}


Upvotes: 2

Related Questions