How to set default clouse param in View method?

I tried to set else default param in ifLet method but I face an error: Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements . What did wrong?

extension View {
    func ifLet<Value, Then: View, Else: View>(
        _ value: Value?,
        then: (Value) -> Then,
        else: () -> Else = { EmptyView() }
    ) -> _ConditionalContent<Then, Else> {
        if let value = value {
            return ViewBuilder.buildEither(first: then(value))
        } else {
            return ViewBuilder.buildEither(second: `else`())
        }
    }
}
struct TestView: View {
    var test: String?

    var body: some View {
        Group {
            ifLet(test) { Text($0) }
            ifLet(test, then: { Text($0) }, else: { Text("Empty") })
        }
    }
}

I think it should be else: () -> Else.

Sorry, I did mistake in my question but my question was about how to set default value of else param.

Stackoverflow guy offers to use two methods. Optional else impossible?

extension View {
    func ifLet<Value, Then: View>(
        _ value: Value?,
        then: (Value) -> Then
    ) -> _ConditionalContent<Then, EmptyView> {
        if let value = value {
            return ViewBuilder.buildEither(first: then(value))
        } else {
            return ViewBuilder.buildEither(second: EmptyView())
        }
    }

    func ifLet<Value, Then: View, Else: View>(
        _ value: Value?,
        then: (Value) -> Then,
        else: () -> Else
    ) -> _ConditionalContent<Then, Else> {
        if let value = value {
            return ViewBuilder.buildEither(first: then(value))
        } else {
            return ViewBuilder.buildEither(second: `else`())
        }
    }
}

It's possible, just use Optional instead of _ConditionalContent.

Here is your correct overload:

func ifLet<T, V>(_ value: T?, then: (T) -> V) -> V? where V: View {
  value.map(then)
}

And as you can see, you can just use map from Optional to produce your view.

// quick example
let optionalString: String? = "swift"

var body: some View {
  optionalString.map { string in 
    Text(string)
  }
}

Optional conditionally conforms to View when Wrapped conforms to View.

1 Like