You might be able to use overloading, as is necessary for your problem when it comes to functions.
It is terrible, yes, but I can't think of a way to avoid copying everything that uses one of the two closure options. I think a generic type is better than two manual concrete types if there's other common functionality that doesn't rely on the closure.
struct Foo<Closure> {
private let closure: Closure
}
extension Foo where Closure == () -> Void {
init(_ closure: Closure) {
self.closure = closure
}
func callAsFunction() {
closure()
}
}
extension Foo where Closure == () throws -> Void {
init(_ closure: Closure) {
self.closure = closure
}
func callAsFunction() throws {
try closure()
}
}
let foo1 = Foo { print("Foo") }
foo1()
let foo2 = Foo {
struct Error: Swift.Error { }
throw Error()
}
do {
try foo2()
} catch {
print("Error")
}