How do I extend ButtonStyle with my generic struct conforming to ButtonStyle?

I created this generic struct that conforms to ButtonStyle (code simplified):

struct FilledButtonStyle<S: ShapeStyle>: ButtonStyle {
    let style: S

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .background(style)
    }
}

I want to create an extension on ButtonStyle that defines a static function that returns this type like this:

extension ButtonStyle where Self == FilledButtonStyle {
    static func filled<S: ShapeStyle>(_ style: S) -> FilledButtonStyle<S> {
        FilledButtonStyle(style: style)
    }
}

I got an error on the extension line: "Reference to generic type 'FilledButtonStyle' requires arguments in <...>".

At this point I got stuck, things I have tried include:

extension ButtonStyle where Self == FilledButtonStyle<S>, S: ShapeStyle {
...
}

This gives an error "Cannot find type 'S' in scope"
I also tried using the some keyword in the FilledButtonStyle definition and in the extension, I also tried removing the Self constraint from the ButtonStyle extension and defining filled(_:) using generic parameters, this resulted in an error when using it in the call site .buttonStyle(.filled(.red)).

I'm starting to think that there is no way to extend ButtonStyle with a type generic over ShapeStyle like this.

Any idea why this is an error and if it's possible to extend button style like this?

When you can't constrain the extension due to generics, you can still constrain the method itself:

extension ButtonStyle {
    static func filled<S: ShapeStyle>(_ style: S) -> FilledButtonStyle<S>
    where Self == FilledButtonStyle<S>
    {
        FilledButtonStyle(style: style)
    }
}
2 Likes

TIL! Thank you @gwendal.roue. I appreciate your time!

1 Like